You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
8.5 KiB
272 lines
8.5 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft OLE
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1997.
|
|
//
|
|
// File: dumpcmd.cpp
|
|
//
|
|
// Contents: dump commandline intelligently
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 07/29/97 SCousens Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <dfheader.hxx>
|
|
#pragma hdrstop
|
|
|
|
// Debug Object declaration
|
|
DH_DECLARE;
|
|
|
|
|
|
struct _options
|
|
{
|
|
LPTSTR name;
|
|
LPTSTR value;
|
|
};
|
|
|
|
#define CHSLASH TEXT('/')
|
|
#define CHDASH TEXT('-')
|
|
#define SAFESTRING(a) a ? a : TEXT("")
|
|
#define ABORTIF(a,b) if (a) {hr = b; goto EndOfFunction;}
|
|
|
|
#define FindNextToken(ptr, tok) \
|
|
while (TEXT('\0') != *(ptr) && tok != (*(ptr))) ++(ptr);
|
|
|
|
inline LPTSTR StringToken (LPTSTR ptr, TCHAR tok)
|
|
{
|
|
FindNextToken (ptr, tok);
|
|
if (tok == *ptr) *ptr = NULL;
|
|
else if (TEXT('\0') == *ptr) ptr = NULL;
|
|
return ptr;
|
|
}
|
|
|
|
|
|
CONST TCHAR chNull = TEXT('\0');
|
|
|
|
CONST TCHAR szCmdLine[] = TEXT("CommandLine:"); // Used DumpCmdLine
|
|
CONST TCHAR szCmdLineFail[] = TEXT("CommandLineFail:"); // Used DumpCmdLine
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
// Member: DumpCmdLine, public
|
|
//
|
|
// Synopsis: Gets the commandline via GetCommandLine, appends the
|
|
// given string to it (additional options to reproduce
|
|
// particular test), and calls TraceMsg to output it.
|
|
// Depending on fResult, the key word 'CommandLine' or
|
|
// 'CommandLineFail' will be prepended.
|
|
//
|
|
// Arguments: [fResult]- Pass or fail (to choose keyword).
|
|
// [pszFmt] - Trace message format string.
|
|
// [...] - Arguments for format string.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
// History: 09-Oct-97 SCousens Created
|
|
//--------------------------------------------------------------------
|
|
void DumpCmdLine (DWORD fResult, LPTSTR pszFmt, ...)
|
|
{
|
|
va_list varArgs;
|
|
LPCTSTR ptKeyWord, ptCmdLine;
|
|
TCHAR szBuffer[CCH_MAX_DBG_CHARS];
|
|
LPTSTR pRepro = NULL;
|
|
|
|
// figure out what key word to use
|
|
ptKeyWord = (LOG_FAIL == fResult) ? szCmdLineFail : szCmdLine;
|
|
|
|
// set our buffer...if we are given something format it nicely
|
|
if (NULL != pszFmt && TCHAR('\0') != *pszFmt)
|
|
{
|
|
// format what we are given in the way of text.
|
|
va_start(varArgs, pszFmt);
|
|
_vsntprintf(szBuffer, CCH_MAX_DBG_CHARS, pszFmt, varArgs);
|
|
szBuffer[CCH_MAX_DBG_CHARS-1] = chNull;
|
|
va_end(varArgs);
|
|
}
|
|
else
|
|
{
|
|
szBuffer[0] = TCHAR('\0');
|
|
}
|
|
|
|
// Get the CommandLine
|
|
ptCmdLine = GetCommandLine();
|
|
if (NULL == ptCmdLine)
|
|
{
|
|
ptCmdLine = TEXT("GetCmdLine Error");
|
|
}
|
|
|
|
// now merge the two intelligently. parameters override cmdline
|
|
// and dump the commandline and whatever we were given.
|
|
if (S_OK == MergeParams (ptCmdLine, szBuffer, &pRepro))
|
|
{
|
|
DH_TRACE ((DH_LVL_ALWAYS, TEXT("%s:%s"), ptKeyWord, pRepro));
|
|
delete []pRepro;
|
|
}
|
|
else
|
|
{
|
|
DH_TRACE ((DH_LVL_ALWAYS, TEXT("%s:%s %s"),
|
|
ptKeyWord, ptCmdLine, szBuffer));
|
|
}
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
// Member: MergeParams, private
|
|
//
|
|
// Synopsis: Given two sets of parameters, merge the two into one
|
|
// set, without duplication. Last one wins.
|
|
// given
|
|
// program /foo /bar /seed:0 /foo:bar
|
|
// /seed:1234 /ms:rules
|
|
// returns
|
|
// program /foo:bar /bar /seed:1234 /ms:rules
|
|
//
|
|
// Arguments: [cmdline] - contents of GetCommandLine call.
|
|
// [additional] - additional options.
|
|
// [repro] - pointer for resulting string
|
|
//
|
|
// Returns: HRESULT - S_OK or failure
|
|
//
|
|
// History: 10-Nov-97 SCousens Created
|
|
//
|
|
// Notes: Caller must call delete [] on returned buffer
|
|
//--------------------------------------------------------------------
|
|
|
|
HRESULT MergeParams (LPCTSTR ptCmdLine, LPCTSTR ptAdditional, LPTSTR *ptRepro)
|
|
{
|
|
struct _options *pOptions;
|
|
int x, y, n, l;
|
|
int nParams = 1;
|
|
HRESULT hr = S_OK;
|
|
LPTSTR pname, pvalue, pnext, ptr;
|
|
LPTSTR name, value;
|
|
LPTSTR ptCmd = NULL;
|
|
|
|
//validate our inputs/outputs
|
|
DH_VDATESTRINGPTR (ptCmdLine);
|
|
if (ptAdditional)
|
|
DH_VDATESTRINGPTR (ptAdditional);
|
|
DH_VDATEPTROUT (ptRepro, LPTSTR);
|
|
|
|
// copy the strings into one buffer, coz we are going to stomp on them
|
|
// how much space do we need?
|
|
l = _tcslen (ptCmdLine);
|
|
if (ptAdditional)
|
|
l += _tcslen (ptAdditional);
|
|
|
|
//allocate a buffer
|
|
ptCmd = new TCHAR[l + 2];
|
|
ABORTIF (NULL == ptCmd, E_OUTOFMEMORY);
|
|
memset (ptCmd, 0xFA, l+2); //BUGBUG do this to find why we died in
|
|
//FindNextToken at one point. Seem to have
|
|
//had a non-terminated string for some reason.
|
|
|
|
//cat the two strings into the allocd buffer
|
|
l = _stprintf (ptCmd, TEXT("%s"), ptCmdLine);
|
|
if (ptAdditional)
|
|
_stprintf (&ptCmd[l], TEXT(" %s"), ptAdditional);
|
|
|
|
// count # parameters (ie spaces) in CmdLine
|
|
ptr = ptCmd;
|
|
while (NULL != *ptr)
|
|
{
|
|
if (TEXT(' ') == *ptr++)
|
|
nParams++;
|
|
}
|
|
DH_TRACE ((DH_LVL_TRACE4, TEXT("Found %d params"), nParams));
|
|
|
|
// allocate an _options for each possible parameter
|
|
pOptions = new struct _options[nParams];
|
|
ABORTIF (NULL == pOptions, E_OUTOFMEMORY);
|
|
|
|
// go through and setup each of the _options (cmdline and given)
|
|
for (pnext = ptCmd, nParams=0, x=0; NULL != pnext; x++)
|
|
{
|
|
pname = pnext;
|
|
pnext = StringToken (pname, TEXT(' ')); //strtok/strchr equivalent
|
|
if (pnext && NULL == *pnext) //safety check
|
|
pnext++;
|
|
|
|
//ignore emptys caused by extra spaces
|
|
if (NULL == *pname)
|
|
continue;
|
|
|
|
//change '-' to '/' so we are uniform in our comparison
|
|
if (CHDASH == *pname)
|
|
*pname = CHSLASH;
|
|
pvalue = StringToken (pname, TEXT(':'));
|
|
|
|
//deal with option
|
|
name = new TCHAR[_tcslen (pname)+1];
|
|
ABORTIF (NULL == name, E_OUTOFMEMORY);
|
|
_tcscpy (name, pname);
|
|
|
|
// if there is a value, deal with that
|
|
value = 0;
|
|
if (NULL != pvalue)
|
|
{
|
|
pvalue++; //move past ':'
|
|
value = new TCHAR[_tcslen (pvalue)+1];
|
|
ABORTIF (NULL == value, E_OUTOFMEMORY);
|
|
_tcscpy (value, pvalue);
|
|
}
|
|
|
|
//name is pointing to a string for name
|
|
//value is pointing to a string for val, else null
|
|
DH_TRACE ((DH_LVL_TRACE4, TEXT("Item[%d]: name:'%s': value:'%s'"),
|
|
nParams, name, value ? value : TEXT("null")));
|
|
pOptions[nParams].name = name;
|
|
pOptions[nParams].value = value;
|
|
nParams++;
|
|
}
|
|
|
|
// Now go thru and make a repro line without dups.
|
|
// last one wins.
|
|
for (x=0, l=0; x<nParams; x++)
|
|
{
|
|
// if its been used, skip it
|
|
if (0 == pOptions[x].name[0])
|
|
continue;
|
|
|
|
n = x;
|
|
// look for dups, and if we have a dup, use the second one
|
|
for (y=x+1; y<nParams; y++)
|
|
{
|
|
// if its been canned, skip it
|
|
if (0 == pOptions[y].name[0])
|
|
continue;
|
|
if (!_tcsicmp (pOptions[n].name, pOptions[y].name))
|
|
{
|
|
pOptions[n].name[0] = 0; //mark 'old' option as used
|
|
n = y; // This is the one we will use
|
|
}
|
|
}
|
|
|
|
//now n is the last option
|
|
//add option[n] to end of line
|
|
if (x) //prepend space all except 1st
|
|
l+=_stprintf (&ptCmd[l], TEXT(" "));
|
|
l+=_stprintf (&ptCmd[l], TEXT("%s"), pOptions[n].name);
|
|
if (NULL != pOptions[n].value) //add value if there is one
|
|
l+=_stprintf (&ptCmd[l], TEXT(":%s"), pOptions[n].value);
|
|
pOptions[n].name[0] = 0; //mark this option as used
|
|
}
|
|
DH_TRACE ((DH_LVL_TRACE4, TEXT("cmd:%s"), ptCmd));
|
|
|
|
//now delete the _options we allocated
|
|
for (x=0; x<nParams; x++)
|
|
{
|
|
delete []pOptions[x].name;
|
|
delete []pOptions[x].value;
|
|
}
|
|
delete []pOptions;
|
|
|
|
//give them what they really want
|
|
*ptRepro = ptCmd;
|
|
|
|
EndOfFunction:
|
|
return hr;
|
|
}
|
|
|