|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998.
//
// File: tstparam.cxx
//
// Synopsys: Test paramers container class implementation
//
// Classes: CTestParams, CParamNode
//
// Notes: The test parameter containers provide a layer of abstraction
// above the particular ways to pass test parameters -
// (command line, environment, registry...)
//
// History: 10-Sep-1998 georgis created
//
//---------------------------------------------------------------------------
#include "srheader.hxx"
#include <tstparam.hxx>
// Private macros to avoid some easy mistakes
#define RETURN(x) hr=x; goto ErrReturn;
#define ENTER_SYNC \
EnterCriticalSection(&m_sync); \ bEnterSync=TRUE; \ if (!m_bUsed) \ { \ m_bUsed=TRUE; \ hr=NotifyOnFirstUse(); \ if (S_OK!=hr) \ { \ RETURN(hr); \ } \ }
#define LEAVE_SYNC \
if (bEnterSync) \ { \ LeaveCriticalSection(&m_sync); \ }
//+--------------------------------------------------------------------------
//
// Function: CalculateHashValue
//
// Synopsys: Calculates hash value for asciiz string
// (case insensitive)
//
// Parameters: pszName: the string
//
// Returns: the hash value (the first 4 characters are used)
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
DWORD CalculateHashValue(LPCWSTR pwszName) { DH_ASSERT(NULL!=pwszName); DWORD dwLen=(DWORD)wcslen(pwszName); DWORD dwTemp=0; for (DWORD dwIndex=0; dwIndex<2; dwIndex++) { dwTemp<<=16; if (dwIndex<dwLen) { dwTemp|=towlower(pwszName[dwIndex]); } } return dwTemp; };
//+--------------------------------------------------------------------------
//
// Function: Unicode2Escaped
//
// Synopsys: Converts Unicode string to escaped ascii string
//
// Parameters: [in] pwszString: the source unicode string
// [out] ppszString: return the ptr to escaped ascii string here
// [in] dwEscapeMode: Escape mode
//
// History: 10-Nov-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT Unicode2Escaped( LPCWSTR pwszString, char ** ppszString, DWORD dwEscapeMode) { HRESULT hr=S_OK; char * pszEscaped=NULL; char * pszDest=NULL; LPCWSTR pwszSrc=NULL; DWORD dwSize=0; BOOL bNeedEscape=FALSE;
DH_VDATEPTROUT(ppszString,LPSTR); *ppszString=NULL;
// if NULL passed, just return NULL
if (NULL==pwszString) { return S_OK; }
// Count the size needed for the escaped string
dwSize=0;
for (pwszSrc=pwszString; 0!=*pwszSrc; pwszSrc++) { if (ESCAPE_NOTNEEDED(*pwszSrc)) { dwSize++; } else { bNeedEscape=TRUE; dwSize+=5; // $xxxx format
} }
// Allocate memory for the escaped string
// Eventually put the prefix
if ((ESCAPEMODE_PREFIX_ALWAYS==dwEscapeMode)|| (ESCAPEMODE_PREFIX_IFCHANGED==dwEscapeMode)&&bNeedEscape) { pszEscaped=new char [dwSize+2]; // the ESCAPED_MARKER and ending 0
DH_ABORTIF(NULL==pszEscaped,E_OUTOFMEMORY,TEXT("new"));
pszDest=pszEscaped; *pszDest++=ESCAPED_MARKER; } else { pszEscaped=new char [dwSize+1]; // ending 0
DH_ABORTIF(NULL==pszEscaped,E_OUTOFMEMORY,TEXT("new")); pszDest=pszEscaped; }
// Translate
for (pwszSrc=pwszString; 0!=*pwszSrc; pwszSrc++) { if (ESCAPE_NOTNEEDED(*pwszSrc)) { *pszDest++=(char)*pwszSrc; } else { *pszDest++=ESCAPE_CHARACTER; sprintf(pszDest,"%04x",*pwszSrc); pszDest+=4; } } *pszDest=0;
ErrReturn: if (S_OK==hr) { *ppszString=pszEscaped; } else { delete pszEscaped; } return hr; }
//+--------------------------------------------------------------------------
//
// Function: Unicode2Escaped (unicode->unicode)
//
// Synopsys: Converts Unicode string to escaped ascii string
//
// Parameters: [in] pwszString: the source unicode string
// [out] ppwszString: return the ptr to escaped ascii string here
// [in] dwEscapeMode: Escape mode
//
// History: 10-Nov-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT Unicode2Escaped( LPCWSTR pwszString, LPWSTR* ppwszString, DWORD dwEscapeMode) { HRESULT hr=S_OK; char * pszEscaped=NULL;
DH_VDATEPTROUT(ppwszString,LPWSTR);
hr=Unicode2Escaped(pwszString,&pszEscaped,dwEscapeMode);
if ((S_OK==hr)&&(NULL!=pszEscaped)) { hr=CopyString(pszEscaped,ppwszString); } else { *ppwszString=NULL; } delete pszEscaped; return hr; }
//+--------------------------------------------------------------------------
//
// Function: Escaped2Unicode
//
// Synopsys: Converts Unicode string to escaped ascii string
//
// Parameters: [in] pszEscaped: the source escaped ascii string
// [out] ppwszString: return the ptr to unescaped unicode string
// [in] dwEscapeMode: escape mode
//
// History: 10-Nov-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT Escaped2Unicode( const char * pszEscaped, LPWSTR *ppwszString, DWORD dwEscapeMode) { HRESULT hr=S_OK; LPWSTR pwszDest=NULL; LPWSTR pwszUnescaped=NULL; const char * pszSrc=NULL; DWORD dwSize=0; int iTemp=0;
DH_VDATEPTROUT(ppwszString,LPWSTR); *ppwszString=NULL;
// if NULL passed, just return NULL
if (NULL==pszEscaped) { return S_OK; }
// Check for the escaped string marker
switch (dwEscapeMode) { case ESCAPEMODE_PREFIX_ALWAYS: DH_ABORTIF(ESCAPED_MARKER!=*pszEscaped,E_UNEXPECTED, TEXT("Bad escaped source string")); pszEscaped++; break; case ESCAPEMODE_PREFIX_IFCHANGED: if (ESCAPED_MARKER==*pszEscaped) { pszEscaped++; } break; case ESCAPEMODE_PREFIX_NEVER: break; default: hr=E_INVALIDARG; DH_HRCHECK_ABORT(hr,TEXT("Bad escape mode")); }
// Count the size needed for the escaped string
dwSize=0; for (pszSrc=pszEscaped; 0!=*pszSrc; pszSrc++) { if (ESCAPE_CHARACTER==*pszSrc) { pszSrc+=4; } else { DH_ABORTIF(!ESCAPE_NOTNEEDED(*pszSrc),E_UNEXPECTED, TEXT("Bad symbol in the escaped string")); } dwSize++; }
// Allocate memory for the unescaped string
pwszUnescaped=new WCHAR [dwSize+1]; DH_ABORTIF(NULL==pwszUnescaped,E_OUTOFMEMORY,TEXT("new"));
// Translate
pwszDest=pwszUnescaped;
for (pszSrc=pszEscaped; 0!=*pszSrc; pwszDest++) { if (ESCAPE_CHARACTER==*pszSrc) { pszSrc++; // sscanf can read hex, but the output buffer must be
// unsigned integer of the default int size, which is more
// then sizeof(wchar)
sscanf(pszSrc,"%04x",&iTemp); *pwszDest=(WCHAR)iTemp; pszSrc+=4; } else { *pwszDest=(WCHAR)*pszSrc++; } } *pwszDest=0;
ErrReturn: if (S_OK==hr) { *ppwszString=pwszUnescaped; } else { delete pwszUnescaped; } return hr; }
//+--------------------------------------------------------------------------
//
// Function: Escaped2Unicode (unicode->unicode)
//
// Synopsys: Converts Unicode string to escaped ascii string
//
// Parameters: [in] pwszEscaped: the source escaped string (unicode)
// [out] ppwszString: return the ptr to unescaped unicode string
// [in] dwEscapeMode: escape mode
//
// History: 10-Nov-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT Escaped2Unicode( LPCWSTR pwszEscaped, LPWSTR *ppwszString, DWORD dwEscapeMode) { HRESULT hr=S_OK; char *pszTemp=NULL;
DH_VDATEPTROUT(ppwszString,LPWSTR);
if (NULL!=pwszEscaped) { hr=CopyString(pwszEscaped,&pszTemp); } if (S_OK==hr) { hr=Escaped2Unicode(pszTemp,ppwszString,dwEscapeMode); } else { *ppwszString=NULL; } delete pszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Constructor: CParamNode::CParamNode
//
// Synopsys: Initializes the parameter node as empty
//
// Arguments: dwFlags: General param info : source,priority,used
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
CParamNode::CParamNode(DWORD dwFlags) { m_dwFlags=dwFlags; m_pwszName=NULL; m_pwszValue=NULL; m_pNext=NULL; }
//+--------------------------------------------------------------------------
//
// Destructor: CParamNode::~CParamNode
//
// Synopsys: Releases the resources used by the parameter node
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
CParamNode::~CParamNode() { delete m_pwszName; delete m_pwszValue; }
//+--------------------------------------------------------------------------
//
// Method: CParamNode::Init
//
// Synopsys: Allocates memory for parameter Name and Value
//
// Parameters: pszName: the parameter name
// pszValue: the parameter value
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CParamNode::Init(LPCWSTR pwszName, LPCWSTR pwszValue) { HRESULT hr=S_OK; DH_ASSERT(NULL!=pwszName); DH_ASSERT(NULL==m_pwszName); // ensure the object is empty
hr=CopyString(pwszName,&m_pwszName); if (S_OK==hr) { m_dwHashValue=CalculateHashValue(pwszName); if (NULL!=pwszValue) { hr=CopyString(pwszValue,&m_pwszValue); } } return hr; }
//+--------------------------------------------------------------------------
//
// Method: CParamNode::ChangeValue
//
// Synopsys: Changes the parameter value
//
// Parameters: pszValue: the parameter value
// dwFlags: parameter info (source,usage,priority)
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CParamNode::ChangeValue(LPCWSTR pwszValue, DWORD dwFlags) { HRESULT hr=S_OK;
DH_ASSERT(dwFlags>0);
// Ensure we don't override used parameters unless asked
if (PARAMMASK_USAGE & m_dwFlags) { if ((dwFlags & PARAMFLAG_OVERRIDEUSED)&& !(PARAMMASK_USAGE & (m_dwFlags & ~dwFlags))) { RETURN(E_ACCESSDENIED); // Can't override this type of usage
} }
// Ensure we don't override higher priority parameters
if ((dwFlags & PARAMMASK_PRIORITY) < (m_dwFlags & PARAMMASK_PRIORITY)) { if (dwFlags & PARAMFLAG_MUSTSET) { RETURN(E_ACCESSDENIED); } else { RETURN(S_OK); } }
m_dwFlags=dwFlags; delete m_pwszValue; m_pwszValue=NULL;
if (NULL!=pwszValue) { hr=CopyString(pwszValue,&m_pwszValue); }
ErrReturn: return hr; }
//+--------------------------------------------------------------------------
//
// Constructor: CTestParams::CTestParams (public)
//
// Synopsys: Initializes the parameter container as empty
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
CTestParams::CTestParams() { m_pParamsList=NULL; m_dwUsageInfo=PARAMUSAGE_GENERAL; m_bUsed=FALSE; InitializeCriticalSection(&m_sync); }
//+--------------------------------------------------------------------------
//
// Destructor: CTestParams::~CTestParams (public)
//
// Synopsys: Releases the resources used by the parameter container object
//
// History: 15-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
CTestParams::~CTestParams() { EnterCriticalSection(&m_sync);
CParamNode *pNext=NULL; for (CParamNode *pNode=m_pParamsList; NULL!=pNode; pNode=pNext) { pNext=pNode->m_pNext; delete pNode; } DeleteCriticalSection(&m_sync); }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetParam (public, synchronized)
//
// Synopsys: Reads parameter of given name:format
//
// Arguments: pszName: The parameter definition string
// pTarget: the addres of the variable which receives the result
//
// Returns: S_OK on success,
// S_FALSE if the parameter is not present,
// E_FAIL if the format given is incompatible with the param value
// or HRESULT error code (E_INVALIDARG, E_OUTOFMEMORY)
//
// Notes: The parameter definition string must be in format name:format
// where name is the name which identyfies the parameter and
// format shows how to read this parameter.
// E.g. "my_int:%i"
//
// Formats may be of two types:
// 1) Any standard sscanf formats starting with %
// E.g. %i %u %d %lx %s ...
//
// 2) Custom formats
// bool - read BOOL (*pTarget is BOOL)
// cstr - read constant string (*pTarget is const char*)
// astr - heap allocated ascii string (*pTarget is char*)
// tstr - heap allocated TCHAR string (*pTarget is LPTSTR)
// olestr - heap allocated OLESTR string (*pTarget is LPOLESTR)
//
// For the heap allocated formats the string obtained is writable,
// and the caller is responsible for deleting it.
//
// History: 09-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetParam(const char *pszName, void* pTarget) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; LPWSTR pwszTemp=NULL; LPWSTR pwszFormat=NULL; CParamNode *pPrev=NULL; // not used
CParamNode *pNode=NULL;
if ((NULL==pszName)||(NULL==pTarget)) { RETURN(E_INVALIDARG); }
hr=CopyString(pszName,&pwszTemp); if (S_OK!=hr) { RETURN(hr); } pwszFormat=wcschr(pwszTemp,L':');
if (NULL==pwszFormat) { RETURN(E_INVALIDARG); }
*pwszFormat++=0;
ENTER_SYNC; pNode=FindParam(pwszTemp,&pPrev);
// for BOOL we always succed, eventyally seting the parameter
// to FALSE if the switch is not found or has value "FALSE"
if (!_wcsicmp(PARAMFMT_BOOL,pwszFormat)) { if ((NULL!=pNode)&& ((NULL==pNode->m_pwszValue)||_wcsicmp(L"FALSE",pNode->m_pwszValue))) { *(BOOL*)pTarget=TRUE; pNode->MarkAsUsed(m_dwUsageInfo); } else { *(BOOL*)pTarget=FALSE; } RETURN(S_OK); }
if (NULL==pNode) { RETURN(S_FALSE); // Not found
} else { pNode->MarkAsUsed(m_dwUsageInfo); }
// Process standard sscanf formats
if (L'%'==*pwszFormat) { if (NULL==pNode->m_pwszValue) { RETURN(E_FAIL); // Found, but has no value
} if (0<swscanf(pNode->m_pwszValue,pwszFormat,pTarget)) { RETURN(S_OK); } else { RETURN(E_FAIL); // sscanf failed - incompatible format
} } else // custom format
{ hr=GetCustomFmtParam(pwszFormat,pNode->m_pwszValue,pTarget); RETURN(hr); }
ErrReturn: LEAVE_SYNC; delete pwszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetCustomFmtParam (private)
//
// Synopsys: Extracts custom format parameter
//
// Arguments: pszFormat: The custom format.
// pszValue: The value as string
// pTarget: the addres of the variable which receives the result
//
// Custom formats:
// cstr - read constant string (*pTarget is const char*)
// astr - heap allocated ascii string (*pTarget is char*)
// tstr - heap allocated TCHAR string (*pTarget is LPTSTR)
// olestr - heap allocated OLESTR string (*pTarget is LPOLESTR)
//
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetCustomFmtParam(LPCWSTR pwszFormat, LPCWSTR pwszValue, void* pTarget) { HRESULT hr=S_OK; DH_ASSERT(NULL!=pwszFormat); DH_ASSERT(NULL!=pTarget);
// ASCII, allocated in heap
if (!wcscmp(PARAMFMT_ASTR,pwszFormat)) { if (NULL!=pwszValue) { hr=CopyString(pwszValue,(char**)pTarget); RETURN(hr); } else { *(char**)pTarget=NULL; RETURN(E_FAIL); } }
// TSTR allocated in heap
if (!wcscmp(PARAMFMT_TSTR,pwszFormat)) { if (NULL!=pwszValue) { hr=CopyString(pwszValue,(LPTSTR*)pTarget); RETURN(hr); } else { *(LPTSTR*)pTarget=NULL; RETURN(E_FAIL); } }
// OLESTR allocated in heap
if (!wcscmp(PARAMFMT_OLESTR,pwszFormat)) { if (NULL!=pwszValue) { hr=CopyString(pwszValue,(LPOLESTR*)pTarget); RETURN(hr); } else { *(LPOLESTR*)pTarget=NULL; RETURN(E_FAIL); } } // Unknown type
hr=E_FAIL;
ErrReturn: return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::IsPresent (public, synchronized)
//
// Synopsys: Retruns TRUE if the parameter is present
// and FALSE if not or error occurs
//
// Arguments: pszName: The parameter definition string
//
// Note: The preferred way to handle BOOL parameters is
// using GETPARAM*("name:bool"), which enables parameters
// to be overwriten by cmd line e.g.
// registry: REG_SZ myparam (existing, value do not matter)
// cmdline: /myparam:false
// The result of GETPARAM("myparam:bool") is FALSE,
// while IsPresent("myparam") will return TRUE,
// with or without cmdline switch /myparam:false
//
// History: 19-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
BOOL __cdecl CTestParams::IsPresent(const char *pszName, ...) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; LPWSTR pwszTemp=NULL; LPWSTR pwszFormat=NULL; CParamNode *pPrev=NULL; // not used
CParamNode *pNode=NULL;
if (NULL==pszName) { return FALSE; }
// if the param definition string contains format,
// extract name only
if (S_OK!=CopyString(pszName,&pwszTemp)) { return FALSE; }
pwszFormat=wcschr(pwszTemp,L':'); if (NULL!=pwszFormat) { *pwszFormat=0; }
ENTER_SYNC; pNode=FindParam(pwszTemp,&pPrev);
ErrReturn: LEAVE_SYNC; delete pwszTemp; return (NULL!=pNode); }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::SetParam (public)
//
// Synopsys: Sets the parameter of given name:format
//
// Arguments: pszName: The parameter definition string
// pTarget: the addres of the variable containig the param value
//
// Returns: S_OK on success,
// E_FAIL if the format given is incompatible with the param value
// or HRESULT error code (E_INVALIDARG, E_OUTOFMEMORY)
//
// Notes: The parameter definition string must be in format name:format
// where name is the name which identyfies the parameter and
// format shows how to read this parameter.
// E.g. "my_string:cstr"
//
// Formats may be of two types:
// 1) Standard sscanf formats
// Only formats
// %s %d %i %x %ld %lx %u %lu %ld, and %I64* are supported
//
// 2) Custom formats
// bool - read BOOL (*pTarget is BOOL)
// cstr - read constant string (*pTarget is const char*)
// astr - heap allocated ascii string (*pTarget is char*)
// tstr - heap allocated TCHAR string (*pTarget is LPTSTR)
// olestr - heap allocated OLESTR string (*pTarget is LPOLESTR)
//
// For the heap allocated formats the string obtained is writable,
// and the caller is responsible for deleting it.
//
// History: 17-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::SetParam(const char *pszName, void* pTarget, DWORD dwFlags) { HRESULT hr=S_OK; LPWSTR pwszTempName=NULL; LPWSTR pwszFormat=NULL;
if ((NULL==pszName)||(NULL==pTarget)|| (0==(PARAMMASK_SOURCE & dwFlags))) { RETURN(E_INVALIDARG); }
hr=CopyString((char*)pszName,&pwszTempName); if (S_OK!=hr) { RETURN(hr); } pwszFormat=wcschr(pwszTempName,L':');
if (NULL==pwszFormat) { RETURN(E_INVALIDARG); }
*pwszFormat++=0; hr=SetCustomFmtParam(pwszTempName,pwszFormat,pTarget,dwFlags);
ErrReturn: delete pwszTempName; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::SetCustomFmtParam (private)
//
// Synopsys: Adds custom format parameter
//
// Arguments: pszName: The parameter name
// pszFormat: The custom format.
// pTarget: the addres of the variable which contains the value
//
// Custom formats:
// bool - BOOL (*pTarget is BOOL)
// cstr - ascii string (*pTarget is char*)
// tstr - TCHAR string (*pTarget is LPTSTR)
// olestr - OLESTR string (*pTarget is LPOLESTR)
//
//
// History: 17-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::SetCustomFmtParam( LPCWSTR pwszName, LPCWSTR pwszFormat, void* pTarget, DWORD dwFlags) { HRESULT hr=S_OK; DH_ASSERT(NULL!=pwszName); DH_ASSERT(NULL!=pwszFormat); DH_ASSERT(NULL!=pTarget); DH_ASSERT((PARAMMASK_SOURCE & dwFlags)>0); LPWSTR pwszTempValue=NULL; WCHAR wszTemp[21]; // enough to print even 64bit integers
// BOOL
if (!wcscmp(PARAMFMT_BOOL,pwszFormat)) { if (*(BOOL*)pTarget) { hr=AddParam(pwszName,NULL,dwFlags); RETURN(hr); } else { hr=AddParam(pwszName,L"FALSE",dwFlags); RETURN(hr); } }
// Int
if (!_wcsicmp(L"%i",pwszFormat)|| !_wcsicmp(L"%d",pwszFormat)|| !_wcsicmp(L"%u",pwszFormat)|| !_wcsicmp(L"%lu",pwszFormat)|| !_wcsicmp(L"%lx",pwszFormat)|| !_wcsicmp(L"%ld",pwszFormat)|| !_wcsicmp(L"%x",pwszFormat)) { if (1>swprintf(wszTemp,pwszFormat,*(long*)pTarget)) { RETURN(E_FAIL); } hr=AddParam(pwszName,wszTemp,dwFlags); RETURN(hr); }
// I64 values
if (!_wcsnicmp(L"%I64",pwszFormat,4)) { if (1>swprintf(wszTemp,pwszFormat,*(ULONGLONG*)pTarget)) { RETURN(E_FAIL); } hr=AddParam(pwszName,wszTemp,dwFlags); RETURN(hr); }
// CONST ASCII - just pass the pszValue as pointer
if (!_wcsicmp(L"%s",pwszFormat)) { hr=AddParam(pwszName,(LPCWSTR)pTarget,dwFlags); RETURN(hr); }
// ASTR
if (!wcscmp(PARAMFMT_ASTR,pwszFormat)) { if (NULL!=*(char*)pTarget) { hr=CopyString((char*)pTarget,&pwszTempValue); } if (S_OK==hr) { hr=AddParam(pwszName,pwszTempValue,dwFlags); } RETURN(hr); }
// TSTR
if (!wcscmp(PARAMFMT_TSTR,pwszFormat)) { if (NULL!=*(LPTSTR*)pTarget) { hr=CopyString((LPTSTR)pTarget,&pwszTempValue); } if (S_OK==hr) { hr=AddParam(pwszName,pwszTempValue,dwFlags); } RETURN(hr); }
// OLESTR
if (!_wcsicmp(PARAMFMT_OLESTR,pwszFormat)) { if (NULL!=*(LPOLESTR*)pTarget) { hr=CopyString((LPOLESTR)pTarget,&pwszTempValue); } if (S_OK==hr) { hr=AddParam(pwszName,pwszTempValue,dwFlags); } RETURN(hr); } // Unknown type
hr=E_INVALIDARG;
ErrReturn: delete pwszTempValue; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::FindParam (private)
//
// Synopsys: Finds given parameter in the list
//
// Arguments: pszName: Parameter name
// ppPrev: if not NULL, retrun the previous node here on success
//
// Returns: Pointer to the parmeter node
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
CParamNode* CTestParams::FindParam(LPCWSTR pwszName, CParamNode** ppPrev) { CParamNode *pNode=NULL; DH_ASSERT(NULL!=pwszName); DH_ASSERT(NULL!=ppPrev);
DWORD dwHashValue=CalculateHashValue(pwszName);
for (pNode=m_pParamsList; NULL!=pNode; *ppPrev=pNode, pNode=pNode->m_pNext) { if (dwHashValue>pNode->m_dwHashValue) { continue; } else if (dwHashValue<pNode->m_dwHashValue) { return NULL; } else // Equal hash values
{ int i=_wcsicmp(pwszName,pNode->m_pwszName); if (i>0) { continue; } else if (i<0) { return NULL; } else { return pNode; } } } return NULL; };
//+--------------------------------------------------------------------------
//
// Method: CTestParams::AddParam (public, synchronized)
//
// Synopsys: Adds a parameter to the container
//
// Arguments: pszName: The parameter name
// pszValue: The parameter value as string
// dwFlags: Param info (source,priority,usage)
//
// Returns: S_OK on success,
// or HRESULT error code (E_INVALIDARG, E_OUTOFMEMORY)
//
// History: 29-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::AddParam( LPCWSTR pwszName, LPCWSTR pwszValue, DWORD dwFlags, BOOL bWasQuoted) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; CParamNode *pPrev=NULL; CParamNode *pParam=NULL; LPWSTR pwszTemp=NULL;
if ((NULL==pwszName)||(0==(PARAMMASK_SOURCE & dwFlags))) { RETURN(E_INVALIDARG); }
if ((NULL!=pwszValue)&& (ESCAPED_MARKER==*pwszValue)&& (!bWasQuoted)) { hr=Escaped2Unicode(pwszValue,&pwszTemp,ESCAPEMODE_PREFIX_ALWAYS); if (S_OK!=hr) { RETURN(hr); } pwszValue=pwszTemp; }
ENTER_SYNC; pParam=FindParam(pwszName,&pPrev);
if (NULL!=pParam) // The parameter is known => try to change the value
{ hr=pParam->ChangeValue(pwszValue,dwFlags); RETURN(hr); } else // new parameter
{ // Create and initialize new parameter node
pParam=new CParamNode(dwFlags); if (NULL==pParam) { RETURN(E_OUTOFMEMORY); } hr=pParam->Init(pwszName,pwszValue); if (S_OK!=hr) { RETURN(hr); } // Insert in the list
if (NULL==pPrev) { // Add as first node
pParam->m_pNext=m_pParamsList; m_pParamsList=pParam; } else { // Add after pPrev
pParam->m_pNext=pPrev->m_pNext; pPrev->m_pNext=pParam; } RETURN(S_OK); }
ErrReturn: if (S_OK!=hr) { delete pParam; } else // Mark the repro info params as used
{ if (PARAMFLAG_REPROINFO & dwFlags) { pParam->MarkAsUsed(dwFlags); } } LEAVE_SYNC; delete pwszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::DeleteParam (public, synchronized)
//
// Synopsys: Deletes given arameter from the string table
//
// Arguments: pszName: Parameter name
//
// Returns: S_OK if the param was not found or successifully deleted
// or E_INVALIDARG
//
// Notes: Deleting parmeters do not cause reallocation of
// the string table to smaller size.
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::DeleteParam(const char *pszName) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; CParamNode *pPrev=NULL; CParamNode *pParam=NULL; LPWSTR pwszName=NULL;
if (NULL==pszName) { RETURN(E_INVALIDARG); }
hr=CopyString(pszName,&pwszName); if (S_OK!=hr) { RETURN(hr); }
ENTER_SYNC; pParam=FindParam(pwszName, &pPrev);
if (NULL==pParam) { RETURN(S_OK); // the param is not present anyway
} if (NULL==pPrev) { DH_ASSERT(m_pParamsList==pParam); m_pParamsList=pParam->m_pNext; } else { pPrev->m_pNext=pParam->m_pNext; }
ErrReturn: delete pParam; delete pwszName; LEAVE_SYNC; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::ReadCommandLine (public)
//
// Synopsys: Reads all the swithes from the command line
// to the parameter container.
//
// Parameters: pszCommandLine: the command line
// or NULL => use GetCommandLine()
//
// Returns: S_OK on success or E_OUTOFMEMORY
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::ReadCommandLine(LPCTSTR ptszCommandLine, DWORD dwFlags) { LPWSTR pwszCmdLine=NULL; LPWSTR pwszName=NULL; LPWSTR pwszValue=NULL; LPWSTR pwszEnd=NULL; HRESULT hr=S_OK; BOOL bQuoted=FALSE;
// If the ptszCommandLine is not given use GetCommandLine
if (NULL!=ptszCommandLine) { hr=CopyString(ptszCommandLine,&pwszCmdLine); if(S_OK!=hr) { RETURN(hr); } } else { hr=CopyString(GetCommandLine(),&pwszCmdLine); if(S_OK!=hr) { RETURN(hr); } }
// Loop for command line switches
pwszName=pwszCmdLine; while ((NULL!=pwszName)&&(0!=*pwszName)) { bQuoted=FALSE;
// Find switch begining with /
while ((0!=*pwszName)&&('/'!=*pwszName)) { pwszName++; } if (0==*pwszName) { RETURN(S_OK); }
// Find switch value
pwszValue=++pwszName; while ((0!=*pwszValue)&&(' '!=*pwszValue)&&(':'!=*pwszValue)) { pwszValue++; } switch (*pwszValue) { case 0: // we hit the end
pwszEnd=NULL; pwszValue=NULL; break; case ' ': // parameter has no value
pwszEnd=pwszValue; *pwszEnd++=0; pwszValue=NULL; break; case ':': // parameter with value
*pwszValue++=0; if ('"'!=*pwszValue) //string without spaces
{ pwszEnd=pwszValue; while ((0!=*pwszEnd)&&(' '!=*pwszEnd)) { pwszEnd++; } if (0!=*pwszEnd) { *pwszEnd++=0; } else { pwszEnd=NULL; } } else // get quoted string
{ pwszEnd=++pwszValue; while ((0!=*pwszEnd)&&('"'!=*pwszEnd)) { pwszEnd++; } if ('"'==*pwszEnd) { *pwszEnd++=0; bQuoted=TRUE; break; } else // the string ended before the closing quote
{ RETURN(E_UNEXPECTED); } } } // case end
hr=AddParam(pwszName,pwszValue,dwFlags,bQuoted); if (S_OK!=hr) { RETURN(hr); } pwszName=pwszEnd; }// parameter loop end
ErrReturn: delete pwszCmdLine; return hr; };
//+--------------------------------------------------------------------------
//
// Method: CTestParams::ReadEnvironment (public)
//
// Synopsys: Copies all the environment vars to the parameter container.
//
// Returns: S_OK on success,
// or HRESULT error code (E_UNEXPECTED, E_OUTOFMEMORY)
//
// Note: The prefix should be always in upper case
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::ReadEnvironment(LPCWSTR pwszPrefix, DWORD dwFlags) { HRESULT hr=S_OK; LPWSTR pwszTemp=NULL; LPWSTR pwszName=NULL; LPWSTR pwszValue=NULL; int i=0; int iLen=0;
// HACK - call getenv so that the system will create environment
// which can be accessed using the _tenviron
_tgetenv(TEXT("COMPUTRNAME")); if (NULL==_tenviron) { RETURN(E_UNEXPECTED); }
// Prepare the prefix length
if (NULL!=pwszPrefix) { iLen=(int)wcslen(pwszPrefix); }
for (i=0; NULL!=_tenviron[i]; i++) { hr=CopyString(_environ[i],&pwszTemp); if (S_OK!=hr) { RETURN(hr); }
pwszValue=wcschr(pwszTemp,L'='); DH_ASSERT(NULL!=pwszValue) *pwszValue++=0; // cut the param name, get the value
if ((NULL==pwszPrefix)|| // no prefix
(!_wcsnicmp(pwszPrefix,pwszTemp,iLen))) // prefix maches
{ pwszName=pwszTemp+iLen; // cut the prefix
hr=AddParam(pwszName,pwszValue,dwFlags); if (S_OK!=hr) { RETURN(hr); } } delete pwszTemp; pwszTemp=NULL; }
ErrReturn: delete pwszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::ReadRegistry (public)
//
// Synopsys: Reads the string values in the given registry key
// to the parameter container
//
// Returns: S_OK on success,
// or HRESULT error code (E_INVALIDARG, E_OUTOFMEMORY)
//
// Note: All non-string values under this key are currently ignored,
// as well as all too large string.
//
// Returns: S_OK on success, or HRESULT error code
//
// History: 10-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::ReadRegistry(HKEY hBaseKey, LPCTSTR ptszKeyName, DWORD dwFlags) { HRESULT hr=S_OK; DWORD dwResult=ERROR_SUCCESS; HKEY hKey=0; TCHAR atszTempName[MAX_REGSTRLEN]; TCHAR atszTempValue[MAX_REGSTRLEN]; DWORD dwNameSize=0; DWORD dwValueSize=0; DWORD dwType=REG_SZ; int i=0;
if ((0==hBaseKey)||(NULL==ptszKeyName)) { RETURN(E_INVALIDARG); }
dwResult=RegOpenKey(hBaseKey,ptszKeyName,&hKey); if ((ERROR_SUCCESS!=dwResult)||(0==hKey)) { RETURN(HRESULT_FROM_WIN32(dwResult)); }
// Loop for all the registry values
for (i=0; dwResult==ERROR_SUCCESS; i++) { dwNameSize = ARRAYSIZE(atszTempName); dwValueSize = ARRAYSIZE(atszTempValue); dwResult=RegEnumValue( hKey, i, (LPTSTR)atszTempName, &dwNameSize, NULL, &dwType, (BYTE*)atszTempValue, &dwValueSize); if (ERROR_NO_MORE_ITEMS==dwResult) { RETURN(S_OK); } else if (ERROR_SUCCESS==dwResult) { // We won't take very big strings, or not strings
if ((dwType!=REG_SZ)|| (dwNameSize>=ARRAYSIZE(atszTempName))|| (dwValueSize>=ARRAYSIZE(atszTempValue))) { // BUGBUG: trace warning here
continue;
} else { #ifndef UNICODE
WCHAR awszTempName[MAX_REGSTRLEN]; WCHAR awszTempValue[MAX_REGSTRLEN];
hr = CopyString(atszTempName, awszTempName, ARRAYSIZE(atszTempName)-1, ARRAYSIZE(atszTempName)-1); if (S_OK!=hr) { RETURN(hr); }
hr = CopyString(atszTempValue, awszTempValue, ARRAYSIZE(atszTempValue)-1, ARRAYSIZE(atszTempValue)-1); if (S_OK!=hr) { RETURN(hr); }
HRESULT hr=AddParam( awszTempName, awszTempValue, dwFlags); #else
HRESULT hr=AddParam( atszTempName, atszTempValue, dwFlags); #endif
if (S_OK!=hr) { RETURN(hr); } } } else if (ERROR_MORE_DATA==dwResult) { // BUGBUG:Trace warning here
continue; // acceptable error - proceed with other params
} }
ErrReturn: if (0!=hKey) { RegCloseKey(hKey); } return hr; };
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetEnum (public, synchronized)
//
// Synopsis: Interprets parameter string value
// as enum DWORD.
//
// Parameters: pszSwitchName: the command line switch name.
// pdwValue: ptr to enum var which receives the result
// ... expected value names and values untill NULL
//
// Example: g_TestParams.GetParamAsEnum(
// "mode",
// &dwMode,
// "rw", STGM_READWRITE,
// "r", STGM_READ,
// "w", STGM_WRITE,
// NULL);
//
// Returns: S_OK on success HRESULT error code
//
// Note: If the parameter is not found the function succeeds and
// retruns the first option value in *pdwValue
//
// History: 15-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT __cdecl CTestParams::GetEnum(const char *pszParamName, DWORD *pdwValue,...) { HRESULT hr=S_OK; char * pszOption=NULL; DWORD dwValue=0xabcdabcd; BOOL bFound=FALSE; BOOL bEnterSync=FALSE; va_list ARGS; CParamNode *pPrev=NULL; // not used
CParamNode *pNode=NULL; char * pszTemp=NULL; LPWSTR pwszName=NULL;
if ((NULL==pszParamName)||(NULL==pdwValue)) { RETURN(E_INVALIDARG); }
// copy the name as unicode
hr=CopyString(pszParamName,&pwszName); if (S_OK!=hr) { RETURN(hr); }
// Get the switch string value
ENTER_SYNC; pNode=FindParam(pwszName,&pPrev); if (NULL!=pNode) { pNode->MarkAsUsed(m_dwUsageInfo); }
// Copy the value as ascii
if ((NULL!=pNode)&&(NULL!=pNode->m_pwszValue)) { hr=CopyString(pNode->m_pwszValue,&pszTemp); if (S_OK!=hr) { RETURN(hr); } }
// Loop for all expected values
va_start(ARGS,pdwValue); pszOption=va_arg(ARGS,char*); while(NULL!=pszOption) { dwValue=va_arg(ARGS,DWORD); if ((NULL==pszTemp)|| (!_stricmp(pszTemp,pszOption))) { bFound=TRUE; break; } pszOption=va_arg(ARGS,char*); } va_end(ARGS);
if (bFound) { *pdwValue=dwValue; hr=S_OK; } else { hr=E_FAIL; }
ErrReturn: LEAVE_SYNC; delete pwszName; delete pszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::ClearUsage (public, synchronized)
//
// Synopsys: Clears usage specific flags
//
// Parameters: dwFlags: DWORD containing the usage flags to clear
// (all other bits are ignored)
//
// History: 30-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
void CTestParams::ClearUsage(DWORD dwFlags) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; CParamNode **pLinkPtr=&m_pParamsList; CParamNode *pNode=m_pParamsList; CParamNode *pNext=NULL;
ENTER_SYNC; while (NULL!=pNode) { pNode->ClearUsage(dwFlags); pNext=pNode->m_pNext;
// Clear "repro info" parameters which are out of scope
// (all the usage flags are cleared)
if ((PARAMFLAG_REPROINFO & pNode->m_dwFlags)&& !(PARAMMASK_USAGE & pNode->m_dwFlags)) { *pLinkPtr=pNext; delete pNode; } else { pLinkPtr=&pNode->m_pNext; } pNode=pNext; } ErrReturn: LEAVE_SYNC; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::ChangeParamFlags (public, synchronized)
//
// Synopsys: Change parameter flags (all except usage marks)
//
// Parameters: dwFlags: DWORD containing the flags
// (usage bits are ignored)
//
// Note: This function may be used for changing priority
// of the parameters from given source
// e.g. ???.ChangeParam(
// PARAMFLAGS_CMDLINE,
// PARAMFLAGS_CMDLINE+1); // raise priority
//
// History: 30-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::ChangeFlags(DWORD dwOldFlags, DWORD dwNewFlags) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; CParamNode *pNode=NULL;
if ((0==(PARAMMASK_SOURCE & dwOldFlags))|| (0==(PARAMMASK_SOURCE & dwNewFlags))) { RETURN(E_INVALIDARG); }
ENTER_SYNC; for (pNode=m_pParamsList; NULL!=pNode; pNode=pNode->m_pNext) { if (dwOldFlags==(pNode->m_dwFlags & ~PARAMMASK_SOURCE)) { pNode->ChangeFlags(dwNewFlags); } } ErrReturn: LEAVE_SYNC; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::SaveParams (public, synchronized)
//
// Synopsys: Allocates a memory block and saves all the parameter info
//
// Arguments: *ppcBuffer:[out] the pointer to the buffer with all params
// *pdwSize: [out] the size of the buffer
// dwMask: [in] filter for parameters
//
// Notes: This method enables storing the set of parameters,
// or sending it to different process.
//
// The caller is responsible for deleting the table obtained.
//
// History: 30-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::SaveParams( char **ppcBuffer, DWORD *pdwSize, DWORD dwMask) { HRESULT hr=S_OK; DWORD dwSize=0; CParamNode *pNode=NULL; BOOL bEnterSync=FALSE; char *pcTemp=NULL;
if ((NULL==pdwSize)||(NULL==ppcBuffer)) { RETURN(E_INVALIDARG); } *ppcBuffer=NULL; *pdwSize=0;
ENTER_SYNC; // Calculate the size needed
for (pNode=m_pParamsList; NULL!=pNode; pNode=pNode->m_pNext) { if (pNode->m_dwFlags & dwMask) { dwSize+=sizeof(DWORD)+((DWORD)wcslen(pNode->m_pwszName)+1)*sizeof(WCHAR); if (NULL!=pNode->m_pwszValue) { dwSize+=((DWORD)wcslen(pNode->m_pwszValue)+1)*sizeof(WCHAR)+1; // mark 'y' + string
} else { dwSize++; // mark 0
}; }; }
// Allocate a buffer
*ppcBuffer=new char[dwSize]; if (NULL==*ppcBuffer) { RETURN(E_OUTOFMEMORY); } memset(*ppcBuffer,0,dwSize);
// Copy all parameters
pcTemp=*ppcBuffer; for (pNode=m_pParamsList; NULL!=pNode; pNode=pNode->m_pNext) { if (pNode->m_dwFlags & dwMask) { // Flags
*(DWORD*)(LPVOID)pcTemp=pNode->m_dwFlags; pcTemp+=sizeof(DWORD);
// Name
wcscpy((LPWSTR)pcTemp,pNode->m_pwszName); pcTemp+=(wcslen((LPWSTR)pcTemp)+1)*sizeof(WCHAR);
// Value
if (NULL!=pNode->m_pwszValue) { *pcTemp++='y'; // mark that we have a value
wcscpy((LPWSTR)pcTemp,pNode->m_pwszValue); pcTemp+=(wcslen((LPWSTR)pcTemp)+1)*sizeof(WCHAR); } else { *pcTemp++=0; // mark that there is no value
} } } *pdwSize=dwSize;
ErrReturn: LEAVE_SYNC; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::LoadParams (public, synchronized)
//
// Synopsys: Loads the parameters from memory buffer obtained by
// the CTestParams::Save method
//
// Arguments: pcBuffer: [in] the pointer to the buffer with all params
// dwSize: [in] the size of the buffer
// dwChangeFlags:[in] if not 0, change all parameters flags
//
// Note: The CTestParams object will make a copy of the parameters
// and do not need the buffer anymore.
//
// History: 30-Sep-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::LoadParams( char *pcBuffer, DWORD dwSize, DWORD dwChangeFlags) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; char *pcTemp=pcBuffer; char *pcEndPtr=pcBuffer+dwSize;
if ((0==dwSize)||(NULL==pcBuffer)) { RETURN(E_INVALIDARG); }
ENTER_SYNC; while (pcTemp<pcEndPtr) { // extract Flags
DWORD dwFlags=*(DWORD*)(LPVOID)(pcTemp); pcTemp+=sizeof(DWORD); if (0!=dwChangeFlags) { // Change all flags except the usage
dwFlags=(dwFlags & PARAMMASK_USAGE) | (dwChangeFlags & ~PARAMMASK_USAGE); }
// extract Name
LPWSTR pwszName=(LPWSTR)pcTemp; pcTemp+=(wcslen((LPWSTR)pcTemp)+1)*sizeof(WCHAR);
// extract Value
LPWSTR pwszValue=NULL; if ('y'==*pcTemp) { pwszValue=(LPWSTR)++pcTemp; pcTemp=(char*)pwszValue+(wcslen(pwszValue)+1)*sizeof(WCHAR); } else { pwszValue=NULL; pcTemp++; }
// Add this parameter
HRESULT hr=AddParam(pwszName,pwszValue,dwFlags); if (S_OK!=hr) { RETURN(hr); } }
ErrReturn: LEAVE_SYNC; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetReproLine (public, synchronized)
//
// Synopsys: Extracts repro line including all the parameters
// which mach the mask
//
// Parameters: dwFlags: the mask to filter parameters,
// default is PARAMMASK_USAGE.
// Use PARAMMASK_ALL to get all parameters
//
// The caller is responsible for deleting the table obtained.
//
// History: 01-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetReproLine(LPWSTR *ppwszReproLine, DWORD dwFlags) { HRESULT hr=S_OK; DWORD dwSize=1; // the ending 0 in the string
CParamNode *pNode=NULL; BOOL bEnterSync=FALSE; LPWSTR pwszBuffer=NULL; LPWSTR pwszTemp=NULL;
if (NULL==ppwszReproLine) { RETURN(E_INVALIDARG); }
ENTER_SYNC; // Calculate the size needed
for (pNode=m_pParamsList; NULL!=pNode; pNode=pNode->m_pNext) { if (dwFlags & pNode->m_dwFlags) { dwSize+=(DWORD)wcslen(pNode->m_pwszName)+2; // the name, '/' and space
if (NULL!=pNode->m_pwszValue) { dwSize+=(DWORD)wcslen(pNode->m_pwszValue)+1; // ':' and value
} } }
if (0==dwSize) { hr=CopyString("",&pwszBuffer); RETURN(hr); }
// Allocate a buffer
pwszBuffer=new WCHAR[dwSize]; if (NULL==pwszBuffer) { RETURN(E_OUTOFMEMORY); } memset(pwszBuffer,0,dwSize*sizeof(WCHAR));
// Copy all parameters
pwszTemp=pwszBuffer; for (pNode=m_pParamsList; NULL!=pNode; pNode=pNode->m_pNext) { if (dwFlags & pNode->m_dwFlags) { // Value
if (NULL!=pNode->m_pwszValue) { swprintf(pwszTemp,L"/%s:%s ",pNode->m_pwszName,pNode->m_pwszValue); pwszTemp+=wcslen(pwszTemp); // point to the ending zero
} else { // The parameter has no value (boolean switch)
swprintf(pwszTemp,L"/%s ",pNode->m_pwszName); pwszTemp+=wcslen(pwszTemp); // point to the ending zero
}; } }
ErrReturn: LEAVE_SYNC; if (S_OK==hr) { *ppwszReproLine=pwszBuffer; } else { delete pwszBuffer; } return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetReproLine (public, synchronized)
//
// Synopsys: Extracts repro line including all the parameters
// which mach the mask
//
// Parameters: dwFlags: the mask to filter parameters,
// default is PARAMMASK_USAGE.
// Use PARAMMASK_ALL to get all parameters
//
// The caller is responsible for deleting the table obtained.
//
// History: 01-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetReproLine(char **ppszReproLine, DWORD dwFlags) { HRESULT hr=S_OK; LPWSTR pwszTemp=NULL;
if (NULL==ppszReproLine) { RETURN(E_INVALIDARG); }
hr=GetReproLine(&pwszTemp,dwFlags); if (S_OK==hr) { if (NULL==pwszTemp) { *ppszReproLine=NULL; } else { hr=CopyString(pwszTemp,ppszReproLine); } } ErrReturn: delete pwszTemp; return hr; }
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetRange (public, synchronized)
//
// Synopsys: Gets the values treating the parameter as range min-max
//
//
// Parameters: pszParamName: [in] the parameter name
// pullMin,pullMin : [out] the range values
//
// Retruns: S_OK or HRESULT error code
//
// Note: The string value of the parameter should be "min-max"
// e.g. "10-20"
// If the parameter can't be found, or the string format is bad
// the values won't be chenged.
//
// History: 02-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetRange( const char *pszParamName, ULONGLONG *pullMin, ULONGLONG *pullMax) { HRESULT hr=S_OK; BOOL bEnterSync=FALSE; CParamNode *pPrev=NULL; // not used
CParamNode *pNode=NULL; LPWSTR pwszMin=NULL; LPWSTR pwszMax=NULL; ULONGLONG ullMin=0; ULONGLONG ullMax=0; LPWSTR pwszName=NULL;
if ((NULL==pszParamName)||(NULL==pullMin)||(NULL==pullMax)) { RETURN(E_INVALIDARG); }
hr=CopyString(pszParamName,&pwszName); if (S_OK!=hr) { RETURN(hr); }
// Get the switch string value
ENTER_SYNC; pNode=FindParam(pwszName,&pPrev);
if ((NULL==pNode)||(NULL==pNode->m_pwszValue)) { RETURN(S_FALSE); } pwszMin = pNode->m_pwszValue; pwszMax = pwszMin; // Advance the maximum pointer past the dash delimeter after
while ((*pwszMax != 0) && (*pwszMax++ != '-')) { ; }
#ifdef WINNT // only here we have functions to hangle 64bit integers
ullMin = _wtoi64(pwszMin); ullMax = _wtoi64(pwszMax); #else
// wtoi64 is not present in link libraries, ifdef this
// to avoid build break. BUGBUG param values >DWORD will be truncated!
ullMin = _wtol(pwszMin); ullMax = _wtol(pwszMax); #endif
if (0==*pwszMax) // only one value is given
{ ullMax=ullMin; };
if (ullMin <= ullMax) { hr=S_OK; *pullMin=ullMin; *pullMax=ullMax; } else { hr=E_FAIL; } ErrReturn: LEAVE_SYNC; delete pwszName; return hr; };
//+--------------------------------------------------------------------------
//
// Method: CTestParams::GetRange (public, synchronized)
//
// Synopsys: Gets the values treating the parameter as range min-max
//
// Parameters: pszParamName: [in] the parameter name
// pulMin,pulMin : [out] the range values
//
// Retruns: S_OK or HRESULT error code
//
// Note: The string value of the parameter should be "min-max"
// e.g. "10-20"
// If the parameter can't be found, or the string format is bad
// the values won't be chenged.
//
// History: 02-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CTestParams::GetRange( const char *pszParamName, ULONG *pulMin, ULONG *pulMax) { HRESULT hr=S_OK; ULARGE_INTEGER uliMin; ULARGE_INTEGER uliMax;
if ((NULL==pszParamName)||(NULL==pulMin)||(NULL==pulMax)) { RETURN(E_INVALIDARG); }
uliMin.QuadPart=0; uliMax.QuadPart=0;
hr=GetRange(pszParamName,&uliMin.QuadPart,&uliMax.QuadPart);
if (S_OK==hr) // else leave the values in *pulMin and *pulMax untouched
{ DH_ASSERT(0==uliMin.HighPart); *pulMin=uliMin.LowPart; DH_ASSERT(0==uliMax.HighPart); *pulMax=uliMax.LowPart; }
ErrReturn: return hr; };
//************** CTOLESTG specific **************************
// Define the default global parameter container
CStgParams g_TestParams;
//+--------------------------------------------------------------------------
//
// Method: CStgParams::NotifyOnFirstUse (public)
//
// Synopsys: Reads all the common parameter sources for
// the CTOLESTG project
//
// Note: The cleaner way is to implement a single function,
// but we want to start using the CTestParams in the
// common code, without modifying each the main()
// for each of the existing suites (about 50 now)
//
// History: 23-Oct-1998 georgis Created
//
//---------------------------------------------------------------------------
HRESULT CStgParams::NotifyOnFirstUse() { HRESULT hr=S_OK; HRESULT hr1=S_OK; DWORD dwDumpMask=PARAMMASK_ALL;
// command line
hr1=ReadCommandLine(); if (S_OK!=hr1) { hr=hr1; };
if (!GETPARAM_ISPRESENT(STG_CMDLINEONLY)) {
// HKEY_CURRENT_USER\Software\Microsoft\CTOLESTG
// is the switch is not present, act as if it was empty
hr1=ReadRegistry( HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\CTOLESTG"));
// Environment
hr1=ReadEnvironment(L"STG_"); if (S_OK!=hr1) { hr=hr1; }; } // if cmdline only
// Eventually dump all the parameters
if (GETPARAM_ISPRESENT(PARAMDUMP)) { GETPARAM(PARAMDUMP,dwDumpMask); } return hr; };
|