windows-nt/Source/XPSP1/NT/net/upnp/tools/util/util.cpp

927 lines
27 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// util.cpp
//
// utility functions used by updiag.exe
//
#include "pch.h"
#pragma hdrstop
#include "oleauto.h"
#include "ncbase.h"
#include "ncinet.h"
#include "ssdpapi.h"
#include "util.h"
//
// Functions for Standard State Table Operations
//
DWORD Do_Set(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_Assign(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_Toggle(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_Increment(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_Decrement(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_IncrementWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_DecrementWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_IncrementBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_DecrementBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_NextStringWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_PrevStringWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_NextStringBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
DWORD Do_PrevStringBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs);
//
// List of Standard State Table Operations
//
extern const STANDARD_OPERATION_LIST c_Ops =
{
// total number of standard operations
13,
{
// Operation name, # of arguments, # of constants, actual function
{ TEXT("SET"), 0, 1, Do_Set},
{ TEXT("ASSIGN"), 1, 0, Do_Assign},
{ TEXT("TOGGLE"), 0, 0, Do_Toggle},
{ TEXT("INCREMENT"), 0, 0, Do_Increment},
{ TEXT("DECREMENT"), 0, 0, Do_Decrement},
{ TEXT("INCREMENT_WRAP"), 0, 2, Do_IncrementWrap},
{ TEXT("DECREMENT_WRAP"), 0, 2, Do_DecrementWrap},
{ TEXT("INCREMENT_BOUNDED"), 0, 1, Do_IncrementBounded},
{ TEXT("DECREMENT_BOUNDED"), 0, 1, Do_DecrementBounded},
{ TEXT("NEXT_STRING_WRAP"), 0, 0, Do_NextStringWrap},
{ TEXT("PREV_STRING_WRAP"), 0, 0, Do_PrevStringWrap},
{ TEXT("NEXT_STRING_BOUNDED"), 0, 0, Do_NextStringBounded},
{ TEXT("PREV_STRING_BOUNDED"), 0, 0, Do_PrevStringBounded},
},
};
VOID WcharToTcharInPlace(LPTSTR szT, LPWSTR szW)
{
DWORD cch = wcslen(szW) + 1;
#ifndef UNICODE
WideCharToMultiByte(CP_ACP, 0, szW, cch, szT, cch, NULL, NULL);
#else
lstrcpyW(szT, szW);
#endif
}
//+---------------------------------------------------------------------------
//
// Function: HrSetupOpenConfigFile
//
// Purpose: Open a service's configuration file (INF format)
//
HRESULT HrSetupOpenConfigFile( PCTSTR pszFileName,
UINT* punErrorLine,
HINF* phinf)
{
HRESULT hr;
HINF hinf;
Assert (pszFileName);
Assert (phinf);
// Try to open the file.
//
hinf = SetupOpenInfFile (pszFileName, NULL, INF_STYLE_WIN4, punErrorLine);
if (INVALID_HANDLE_VALUE != hinf)
{
hr = S_OK;
*phinf = hinf;
}
else
{
hr = HrFromLastWin32Error ();
*phinf = NULL;
if (punErrorLine)
{
*punErrorLine = 0;
}
}
TraceHr (ttidError, FAL, hr, FALSE,
"HrSetupOpenConfigFile (%S)", pszFileName);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrSetupFindFirstLine
//
// Purpose: Find the first line in an INF file with a matching section
// and key.
//
HRESULT HrSetupFindFirstLine( HINF hinf,
PCTSTR pszSection,
PCTSTR pszKey,
INFCONTEXT* pctx)
{
Assert (hinf);
Assert (pszSection);
Assert (pctx);
HRESULT hr;
if (SetupFindFirstLine (hinf, pszSection, pszKey, pctx))
{
hr = S_OK;
}
else
{
hr = HrFromLastWin32Error ();
}
TraceErrorOptional ("HrSetupFindFirstLine", hr,
(SPAPI_E_LINE_NOT_FOUND == hr));
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrSetupFindNextLine
//
// Purpose: Find the next line in an INF file relative to ctxIn.
//
HRESULT HrSetupFindNextLine( const INFCONTEXT& ctxIn,
INFCONTEXT* pctxOut)
{
Assert (pctxOut);
HRESULT hr;
if (SetupFindNextLine (const_cast<PINFCONTEXT>(&ctxIn), pctxOut))
{
hr = S_OK;
}
else
{
hr = HrFromLastWin32Error ();
if (SPAPI_E_LINE_NOT_FOUND == hr)
{
// Translate ERROR_LINE_NOT_FOUND into S_FALSE
hr = S_FALSE;
}
}
TraceError ("HrSetupFindNextLine", (hr == S_FALSE) ? S_OK : hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetStringField
//
// Purpose: Gets a string from an INF field.
//
HRESULT HrSetupGetStringField( const INFCONTEXT& ctx,
DWORD dwFieldIndex,
PTSTR pszBuf,
DWORD cchBuf,
DWORD* pcchRequired)
{
HRESULT hr;
if (SetupGetStringField ((PINFCONTEXT)&ctx, dwFieldIndex, pszBuf,
cchBuf, pcchRequired))
{
hr = S_OK;
}
else
{
hr = HrFromLastWin32Error ();
if (pszBuf)
{
*pszBuf = 0;
}
if (pcchRequired)
{
*pcchRequired = 0;
}
}
TraceError ("HrSetupGetStringField", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetLineText
//
// Purpose: Gets a line from an INF field.
//
HRESULT HrSetupGetLineText( const INFCONTEXT& ctx,
PTSTR pszBuf,
DWORD cchBuf,
DWORD* pcchRequired)
{
HRESULT hr;
if (SetupGetLineText((PINFCONTEXT)&ctx, NULL, NULL, NULL, pszBuf,
cchBuf, pcchRequired))
{
hr = S_OK;
}
else
{
hr = HrFromLastWin32Error ();
if (pszBuf)
{
*pszBuf = 0;
}
if (pcchRequired)
{
*pcchRequired = 0;
}
}
TraceError ("HrSetupGetStringField", hr);
return hr;
}
VOID SetupCloseInfFileSafe(HINF hinf)
{
if (IsValidHandle(hinf))
{
SetupCloseInfFile(hinf);
}
}
// get the next field
// returns FALSE if field not found or is empty
BOOL fGetNextField(TCHAR ** pszLine, TCHAR * szBuffer)
{
Assert(*pszLine);
Assert(szBuffer);
*szBuffer = '\0';
if (lstrlen(*pszLine))
{
TCHAR * pChar;
if (**pszLine == '(')
{
pChar = _tcschr(*pszLine, TEXT(')'));
pChar++;
}
else
{
pChar = _tcschr(*pszLine, TEXT(','));
}
if (pChar)
{
*pChar ='\0';
lstrcpy(szBuffer, *pszLine);
*pszLine = ++pChar;
}
else
{
lstrcpy(szBuffer, *pszLine);
**pszLine = '\0';
}
}
return (!!lstrlen(szBuffer));
}
// Input: name of the operation
// Output: number of arguments and constants
BOOL IsStandardOperation(TCHAR * szOpName, DWORD * pnArgs, DWORD * pnConsts)
{
*pnArgs =0;
*pnConsts=0;
for (DWORD iOps = 0; iOps < c_Ops.cOperations; iOps++)
{
if (!_tcsicmp(c_Ops.rgOperations[iOps].szOperation, szOpName))
{
*pnArgs = c_Ops.rgOperations[iOps].nArguments;
*pnConsts = c_Ops.rgOperations[iOps].nConstants;
return TRUE;
}
}
return FALSE;
}
// Find the row in the state table that needs to be changed
//
SST_ROW * FindSSTRowByVarName(SST * psst, TCHAR * szVariableName)
{
SST_ROW * pRow = NULL;
for (DWORD iRow =0; iRow<psst->cRows; iRow++)
{
if (!lstrcmpi(psst->rgRows[iRow].szPropName, szVariableName))
{
pRow = &psst->rgRows[iRow];
break;
}
}
return pRow;
}
//
// Functions for Standard State Table Operations
//
HRESULT HrSetVariantValue(VARIANT * pVar, TCHAR * szNewValue)
{
HRESULT hr;
VARIANT varNew;
VariantInit(&varNew);
varNew.vt = VT_BSTR;
WCHAR * wszNewValue = WszFromTsz(szNewValue);
V_BSTR(&varNew) = SysAllocString(wszNewValue);
hr = VariantChangeType(&varNew, &varNew, 0, pVar->vt);
if (S_OK == hr)
{
hr = VariantCopy(pVar, &varNew);
}
TraceError("HrSetVariantValue", hr);
return hr;
}
DWORD dwSubmitEvent(UPNPSVC * psvc, SST_ROW * pRow)
{
HRESULT hr;
DWORD dwErr =0;
CHAR szUri[INTERNET_MAX_URL_LENGTH];
UPNP_PROPERTY Property = {0};
// convert current value to string
VARIANT varValue;
VariantInit(&varValue);
hr = VariantChangeType(&varValue, &pRow->varValue, 0, VT_BSTR);
if (S_OK ==hr)
{
LPSTR pszUrl = SzFromTsz(psvc->szEvtUrl);
if (pszUrl)
{
LPWSTR wszVal = varValue.bstrVal;
Property.szValue = SzFromWsz(wszVal);
if (Property.szValue)
{
hr = HrGetRequestUriA(pszUrl, INTERNET_MAX_URL_LENGTH, szUri);
if (SUCCEEDED(hr))
{
if (SubmitUpnpPropertyEvent(szUri, 0, 1, &Property))
{
TraceTag(ttidUpdiag, "Successfully submitted event to %s.", psvc->szEvtUrl);
}
else
{
dwErr =1;
TraceTag(ttidUpdiag, "Failed to submit event to %s! Error %d.",
psvc->szEvtUrl, GetLastError());
}
}
else
{
dwErr =1;
TraceTag(ttidUpdiag, "Failed to crack URL %s! Error %d.",
psvc->szEvtUrl, GetLastError());
}
delete [] Property.szValue;
}
else
{
dwErr =1;
TraceTag(ttidUpdiag, "SzFromWsz (#2) failed");
}
}
else
{
dwErr =1;
TraceTag(ttidUpdiag, "SzFromWsz (#1) failed");
}
}
else
{
dwErr =1;
TraceTag(ttidUpdiag, "Failed to convert variable value to string. Error: %x.", hr);
}
return dwErr;
}
DWORD Do_Set(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_Set: set variable %s to constant %s",
pOpData->szVariableName, pOpData->mszConstantList);
DWORD dwError = 0;
Assert(cArgs == 0);
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
HRESULT hr = HrSetVariantValue(&pRow->varValue, pOpData->mszConstantList);
if (S_OK != hr)
{
dwError =1;
}
else
{
dwError = dwSubmitEvent(psvc, pRow);
}
}
return dwError;
};
DWORD Do_Assign(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_Assign: assign variable %s to argument %s",
pOpData->szVariableName, rgArgs[0].szValue);
DWORD dwError = 0;
Assert(cArgs == 1);
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// check if the new value is within the range or is in the allowed value list
if (*pRow->mszAllowedValueList)
{
TCHAR * pNextString = pRow->mszAllowedValueList;
while (*pNextString && (lstrcmpi(rgArgs[0].szValue, pNextString) !=0))
{
pNextString += lstrlen(pNextString);
pNextString ++;
}
if (!*pNextString)
{
TraceTag(ttidUpdiag, "Do_Assign: new variable value is not in the allowed value list !");
dwError =1;
}
}
else if (*pRow->szMin)
{
Assert(*pRow->szMax);
// This should only work if the variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
long lMin = _ttol(pRow->szMin);
long lMax = _ttol(pRow->szMax);
long lVal = _ttol(rgArgs[0].szValue);
if ((lVal<lMin) || (lVal>lMax))
{
TraceTag(ttidUpdiag, "Do_Assign: new variable value is not in the allowed range !");
dwError =1;
}
}
}
if (!dwError)
{
HRESULT hr = HrSetVariantValue(&pRow->varValue, rgArgs[0].szValue);
if (S_OK != hr)
{
dwError =1;
}
else
{
dwError = dwSubmitEvent(psvc, pRow);
}
}
}
return dwError;
};
DWORD Do_Toggle(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_Toggle");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
Assert(pRow->varValue.vt == VT_BOOL);
if (pRow->varValue.vt == VT_BOOL)
{
pRow->varValue.boolVal = ~pRow->varValue.boolVal;
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a boolean.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_Increment(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_Increment");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if teh variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
pRow->varValue.lVal++;
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_Decrement(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_Decrement");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if teh variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
pRow->varValue.lVal--;
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_IncrementWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_IncrementWrap");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
// get the max and min values from the constant list
TCHAR * szMax = pOpData->mszConstantList;
szMax += lstrlen(szMax)+1;
long lMin = _ttol(pOpData->mszConstantList);
long lMax = _ttol(szMax);
Assert(lMax >= lMin);
TraceTag(ttidUpdiag, "Do_IncrementWrap: variable= %d, min= %d, max= %d",
pRow->varValue.lVal, lMin, lMax);
pRow->varValue.lVal = lMin + ((pRow->varValue.lVal-lMin+1) % (lMax-lMin+1));
Assert((lMin<=pRow->varValue.lVal) && (lMax>=pRow->varValue.lVal));
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_DecrementWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_DecrementWrap");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
// get the max and min values from the constant list
TCHAR * szMax = pOpData->mszConstantList;
szMax += lstrlen(szMax)+1;
long lMin = _ttol(pOpData->mszConstantList);
long lMax = _ttol(szMax);
Assert(lMax >= lMin);
TraceTag(ttidUpdiag, "Do_DecrementWrap: variable= %d, min= %d, max= %d",
pRow->varValue.lVal, lMin, lMax);
pRow->varValue.lVal = lMax - ((lMax-pRow->varValue.lVal+1) % (lMax-lMin+1));
Assert((lMin<=pRow->varValue.lVal) && (lMax>=pRow->varValue.lVal));
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_IncrementBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_IncrementBounded");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
// max value is the only constant
long lMax = _ttol(pOpData->mszConstantList);
if (pRow->varValue.lVal < lMax)
{
pRow->varValue.lVal++;
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "IncrementBounded: variable %s already has the maximum value.",
pOpData->szVariableName);
}
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD Do_DecrementBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_DecrementBounded");
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a number ??
Assert(pRow->varValue.vt == VT_I4);
if (pRow->varValue.vt == VT_I4)
{
// max value is the only constant
long lMin = _ttol(pOpData->mszConstantList);
if (pRow->varValue.lVal > lMin)
{
pRow->varValue.lVal--;
dwError = dwSubmitEvent(psvc, pRow);
}
else
{
TraceTag(ttidUpdiag, "DecrementBounded: variable %s already has the minimal value.",
pOpData->szVariableName);
}
}
else
{
TraceTag(ttidUpdiag, "Error: variable %s is not a number.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
};
DWORD dwMoveToNextString(UPNPSVC * psvc, OPERATION_DATA * pOpData, BOOL fWrap)
{
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a string
// and we have a list of allowed values
Assert(pRow->varValue.vt == VT_BSTR);
if (pRow->varValue.vt == VT_BSTR)
{
if (lstrlen(pRow->mszAllowedValueList)>0)
{
TCHAR * pNextString = pRow->mszAllowedValueList;
while (*pNextString && (lstrcmpi(TszFromWsz(pRow->varValue.bstrVal),
pNextString) !=0))
{
pNextString += lstrlen(pNextString);
pNextString ++;
}
if (!*pNextString)
{
TraceTag(ttidUpdiag, "dwSetToNextString: variable value is not in the allowed value list ??");
dwError =1;
}
else
{
// is pNextString the last string in the list ?
TCHAR * pChar = pNextString + lstrlen(pNextString);
pChar++;
if (*pChar)
{
// not the last string
V_BSTR(&pRow->varValue) = SysAllocString(WszFromTsz(pChar));
dwError = dwSubmitEvent(psvc, pRow);
}
else if (fWrap)
{
V_BSTR(&pRow->varValue) =
SysAllocString(WszFromTsz(pRow->mszAllowedValueList));
dwError = dwSubmitEvent(psvc, pRow);
}
}
}
else
{
TraceTag(ttidUpdiag, "dwSetToNextString: variable %s has no list of allowed values.",
pOpData->szVariableName);
dwError =1;
}
}
else
{
TraceTag(ttidUpdiag, "dwSetToNextString: variable %s is not a string.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
}
DWORD dwMoveToPrevString(UPNPSVC * psvc, OPERATION_DATA * pOpData, BOOL fWrap)
{
DWORD dwError = 0;
// find the SST row to update
SST_ROW * pRow = FindSSTRowByVarName(&psvc->sst, pOpData->szVariableName);
Assert(pRow);
if (pRow)
{
// This should only work if the variable is a string
// and we have a list of allowed values
Assert(pRow->varValue.vt == VT_BSTR);
if (pRow->varValue.vt == VT_BSTR)
{
if (lstrlen(pRow->mszAllowedValueList)>0)
{
TCHAR * pNextString = pRow->mszAllowedValueList;
TCHAR * pPrevString = pNextString;
while (*pNextString && (lstrcmpi(TszFromWsz(pRow->varValue.bstrVal),
pNextString) !=0))
{
if (pPrevString != pNextString)
{
pPrevString = pNextString;
}
pNextString += lstrlen(pNextString);
pNextString++;
}
if (!pNextString)
{
TraceTag(ttidUpdiag, "dwSetToNextString: variable value is not in the allowed value list ??");
dwError =1;
}
else
{
// is pNextString the first string in the list ?
if (pNextString != pPrevString)
{
// not the first string
V_BSTR(&pRow->varValue) = SysAllocString(WszFromTsz(pPrevString));
dwError = dwSubmitEvent(psvc, pRow);
}
else if (fWrap)
{
// go to the last string
pNextString += lstrlen(pNextString);
pNextString++;
while (*pNextString)
{
pPrevString = pNextString;
pNextString += lstrlen(pNextString);
pNextString++;
}
V_BSTR(&pRow->varValue) = SysAllocString(WszFromTsz(pPrevString));
dwError = dwSubmitEvent(psvc, pRow);
}
}
}
else
{
TraceTag(ttidUpdiag, "dwMoveToPrevString: variable %s has no list of allowed values.",
pOpData->szVariableName);
dwError =1;
}
}
else
{
TraceTag(ttidUpdiag, "dwMoveToPrevString: variable %s is not a string.",
pOpData->szVariableName);
dwError =1;
}
}
return dwError;
}
DWORD Do_NextStringWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_NextStringWrap");
return dwMoveToNextString(psvc, pOpData, TRUE);
}
DWORD Do_PrevStringWrap(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_PrevStringWrap");
return dwMoveToPrevString(psvc, pOpData, TRUE);
}
DWORD Do_NextStringBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_NextStringBounded");
return dwMoveToNextString(psvc, pOpData, FALSE);
}
DWORD Do_PrevStringBounded(UPNPSVC * psvc, OPERATION_DATA * pOpData, DWORD cArgs, ARG *rgArgs)
{
TraceTag(ttidUpdiag, "Do_PrevStringBounded");
return dwMoveToPrevString(psvc, pOpData, FALSE);
}