|
|
//+----------------------------------------------------------------------------
//
// File: processcmdln.cpp
//
// Module: CMSETUP.LIB
//
// Synopsis: Implementation of the CProcessCmdLn class.
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// Author: quintinb Created Header 08/19/99
//
//+----------------------------------------------------------------------------
#include "cmsetup.h"
#include "setupmem.h"
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::CProcessCmdLn
//
// Synopsis: Inits the class by copying the valid command line switches to the
// command line switch array.
//
// Arguments: UINT NumSwitches - Number of switches in the array
// UINT NumCharsInSwitch - Number of chars in each switch, counting the terminating NULL
// TCHAR pszCommandLineSwitches[][] - Array of command line switches.
//
// Returns: Nothing
//
// History: quintinb Created 7/24/98
//
//+----------------------------------------------------------------------------
CProcessCmdLn::CProcessCmdLn(UINT NumSwitches, ArgStruct* pArrayOfArgStructs, BOOL bSkipFirstToken, BOOL bBlankCmdLnOkay) { m_NumSwitches = NumSwitches; m_bSkipFirstToken = bSkipFirstToken; m_bBlankCmdLnOkay = bBlankCmdLnOkay; m_CommandLineSwitches = NULL;
m_CommandLineSwitches = (ArgStruct*)CmMalloc(m_NumSwitches*sizeof(ArgStruct));
if (m_CommandLineSwitches) { for(UINT i =0; i < NumSwitches; i++) { m_CommandLineSwitches[i].pszArgString = (TCHAR*)CmMalloc(sizeof(TCHAR)*(lstrlen(pArrayOfArgStructs[i].pszArgString) + 1));
if (m_CommandLineSwitches[i].pszArgString) { lstrcpyn(m_CommandLineSwitches[i].pszArgString, pArrayOfArgStructs[i].pszArgString, (lstrlen(pArrayOfArgStructs[i].pszArgString) + 1));
m_CommandLineSwitches[i].dwFlagModifier = pArrayOfArgStructs[i].dwFlagModifier; } } } }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::~CProcessCmdLn
//
// Synopsis: Cleans up after the class by deleting the dynamically allocated
// string.
//
// Arguments: None
//
// Returns: Nothing
//
// History: Created Header 7/24/98
//
//+----------------------------------------------------------------------------
CProcessCmdLn::~CProcessCmdLn() { if (m_CommandLineSwitches) { for(UINT i =0; i < m_NumSwitches; i++) { CmFree(m_CommandLineSwitches[i].pszArgString); } CmFree(m_CommandLineSwitches); } }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::IsValidSwitch
//
// Synopsis: This function tells whether the inputed switch is a recognized
// command line switch.
//
// Arguments: LPCTSTR pszSwitch - Input switch string to be tested
//
// Returns: BOOL - Returns TRUE if the switch passed in is recognized as valid
//
// History: quintinb Created 7/13/98
//
//+----------------------------------------------------------------------------
BOOL CProcessCmdLn::IsValidSwitch(LPCTSTR pszSwitch, LPDWORD pdwFlags) { for (UINT i = 0; i < m_NumSwitches; i++) { if (m_CommandLineSwitches[i].pszArgString && (0 == lstrcmpi(m_CommandLineSwitches[i].pszArgString, pszSwitch))) { //
// Then we have a match
//
*pdwFlags |= m_CommandLineSwitches[i].dwFlagModifier; return TRUE; } }
return FALSE; }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::IsValidFilePath
//
// Synopsis: This file checks to see if the inputted file path is a valid filepath.
// This function depends on setfileattributes.
//
// Arguments: LPCTSTR pszFile - File to check to see if it exists.
//
// Returns: BOOL - Returns TRUE if we can set the attributes of the file inputed.
//
// History: quintinb Created 7/13/98
//
//+----------------------------------------------------------------------------
BOOL CProcessCmdLn::IsValidFilePath(LPCTSTR pszFile) { return SetFileAttributes(pszFile, FILE_ATTRIBUTE_NORMAL); }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::EnsureFullFilePath
//
// Synopsis: This file checks to see if a file path passed in is a full path.
// If it is not a full path then it adds the current directory path
// to the beginning (assuming that we have a filename and extension).
//
// Arguments: LPTSTR pszFile - File to check
// UINT uNumChars - Number of chars in the buffer holding pszFile
//
// Returns: BOOL - TRUE if a full file path
//
// History: quintinb Created 7/24/98
//
//+----------------------------------------------------------------------------
BOOL CProcessCmdLn::EnsureFullFilePath(LPTSTR pszFile, UINT uNumChars) { BOOL bReturn = FALSE;
if (SetFileAttributes(pszFile, FILE_ATTRIBUTE_NORMAL)) { CFileNameParts InstallFileParts(pszFile);
if ((TEXT('\0') == InstallFileParts.m_Drive[0]) && (TEXT('\0') == InstallFileParts.m_Dir[0]) && (TEXT('\0') != InstallFileParts.m_FileName[0]) && (TEXT('\0') != InstallFileParts.m_Extension[0])) { //
// Then we have a filename and extension but we don't
// have a full path. Thus we want to add the current
// directory onto the filename and extension.
//
TCHAR szTemp[MAX_PATH+1];
if (GetCurrentDirectory(MAX_PATH, szTemp)) { if (uNumChars > (UINT)(lstrlen(szTemp) + lstrlen(InstallFileParts.m_FileName) + lstrlen(InstallFileParts.m_Extension) + 2)) { wsprintf(pszFile, TEXT("%s\\%s%s"), szTemp, InstallFileParts.m_FileName, InstallFileParts.m_Extension); bReturn = TRUE; } } } else { //
// Could be a UNC path, a path with a drive letter and filename, or
// a full path with a drive and a dir
//
bReturn = TRUE; } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::CheckIfValidSwitchOrPath
//
// Synopsis: Bundles code to determine if a token is a valid switch or path.
//
// Arguments: LPCTSTR pszToken - current token
// BOOL* pbFoundSwitch - pointer to the BOOL which tells if a switch has been found yet
// BOOL* pbFoundPath - pointer to the BOOL which tells if a path has been found yet
// LPTSTR pszSwitch - string to hold the switch
// LPTSTR pszPath - string to hold the path
//
// Returns: BOOL - returns TRUE if successful
//
// History: quintinb Created 8/25/98
//
//+----------------------------------------------------------------------------
BOOL CProcessCmdLn::CheckIfValidSwitchOrPath(LPCTSTR pszToken, LPDWORD pdwFlags, BOOL* pbFoundPath, LPTSTR pszPath) { if (IsValidSwitch(pszToken, pdwFlags)) { CMTRACE1(TEXT("ProcessCmdLn - ValidSwitch is %s"), pszToken); } else if (!(*pbFoundPath)) { if (IsValidFilePath(pszToken)) { *pbFoundPath = TRUE; lstrcpy(pszPath, pszToken);
CMTRACE1(TEXT("ProcessCmdLn - ValidFilePath is %s"), pszToken); } else { //
// Maybe the path contains environment variables, try to expand them.
//
TCHAR szExpandedPath[MAX_PATH+1] = TEXT("");
CMTRACE1(TEXT("ProcessCmdLn - %s is not a valid path, expanding environment strings"), pszToken); ExpandEnvironmentStrings(pszToken, szExpandedPath, MAX_PATH);
CMTRACE1(TEXT("ProcessCmdLn - expanded path is %s"), szExpandedPath); if (IsValidFilePath(szExpandedPath)) { *pbFoundPath = TRUE; lstrcpy(pszPath, szExpandedPath); } else { //
// Still no luck, return an error
//
CMTRACE1(TEXT("ProcessCmdLn - %s is not a valid path"), szExpandedPath);
return FALSE; } } } else { //
// We don't know what this is, send back an error
//
CMTRACE1(TEXT("ProcessCmdLn - Invalid token is %s"), pszToken); return FALSE; }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: CProcessCmdLn::GetCmdLineArgs
//
// Synopsis: This function looks for any combination of just a command line
// switch, just a path, or both. Handles long paths if quoted.
//
//
// Arguments: IN LPTSTR pszCmdln - the command line to parse
// OUT LPTSTR pszSwitch - Out parameter for the command line switch
// OUT LPTSTR pszPath - Out parameter for the path
//
// Returns: BOOL - Returns TRUE if it was able to parse the args
//
// History: quintinb rewrote InitArgs from cmmgr.cpp to make it
// simpler and more taylored to cmstp. 7-13-98
//
//----------------------------------------------------------------------------
BOOL CProcessCmdLn::GetCmdLineArgs(IN LPTSTR pszCmdln, OUT LPDWORD pdwFlags, OUT LPTSTR pszPath, UINT uPathStrLimit) { LPTSTR pszCurr; LPTSTR pszToken; CMDLN_STATE state; BOOL bFoundSwitch = FALSE; BOOL bFoundPath = FALSE;
if ((NULL == pdwFlags) || (NULL == pszPath)) { return FALSE; }
//
// Init pdwFlags to Zero
//
*pdwFlags = 0;
//
// If m_bSkipFirstToken is TRUE, the we will skip the first Token. Otherwise,
// we won't.
//
BOOL bFirstToken = m_bSkipFirstToken; state = CS_CHAR; pszCurr = pszToken = pszCmdln;
CMTRACE1(TEXT("CProcessCmdLn::GetCmdLineArgs - Command line is %s"), pszCmdln);
do { switch (*pszCurr) { case TEXT(' '): if (state == CS_CHAR) { //
// we found a token
//
*pszCurr = TEXT('\0'); if (bFirstToken) { //
// The first token is the name of the exe, thus throw it away
//
bFirstToken = FALSE; CMTRACE1(TEXT("Throwing away, first token: %s"), pszToken); } else if(!CheckIfValidSwitchOrPath(pszToken, pdwFlags, &bFoundPath, pszPath)) { //
// return an error
//
return FALSE; } *pszCurr = TEXT(' '); pszCurr = pszToken = CharNext(pszCurr); state = CS_END_SPACE; continue; } else if (state == CS_END_SPACE || state == CS_END_QUOTE) { pszToken = CharNext(pszToken); } break;
case TEXT('\"'): if (state == CS_BEGIN_QUOTE) { //
// we found a token
//
*pszCurr = TEXT('\0');
//
// skip the opening quote
//
pszToken = CharNext(pszToken); if (bFirstToken) { //
// The first token is the name of the exe, thus throw it away
//
bFirstToken = FALSE; CMTRACE1(TEXT("Throwing away, first token: %s"), pszToken); } else if(!CheckIfValidSwitchOrPath(pszToken, pdwFlags, &bFoundPath, pszPath)) { //
// return an error
//
return FALSE; } *pszCurr = TEXT('\"'); pszCurr = pszToken = CharNext(pszCurr); state = CS_END_QUOTE; continue; } else { state = CS_BEGIN_QUOTE; } break;
case TEXT('\0'): if (state != CS_END_QUOTE) { if (bFirstToken) { //
// The first token is the name of the exe, thus throw it away
//
bFirstToken = FALSE; CMTRACE1(TEXT("Throwing away, first token: %s"), pszToken); } else if(!CheckIfValidSwitchOrPath(pszToken, pdwFlags, &bFoundPath, pszPath)) { //
// return an error
//
return FALSE; } } state = CS_DONE; break;
default: if (state == CS_END_SPACE || state == CS_END_QUOTE) { state = CS_CHAR; } break; } pszCurr = CharNext(pszCurr); } while (state != CS_DONE);
if (bFoundPath) { //
// Then at least we found a path (and maybe switches, maybe not)
//
return EnsureFullFilePath(pszPath, uPathStrLimit); } else if (0 != *pdwFlags) { //
// Then at least we found a switch
//
return TRUE; } else { //
// If it is okay to have a blank command line, then this is okay, otherwise it isn't.
// Note that if m_bSkipFirstToken == TRUE, then the command line might not be completely
// blank, it could contain the name of the executable for instance.
//
return m_bBlankCmdLnOkay; } }
|