|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C S T R I N G . C P P
//
// Contents: Common string routines.
//
// Notes:
//
// Author: shaunco 24 Mar 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "ncdebug.h"
#include "ncstring.h"
//+---------------------------------------------------------------------------
//
// Function: CbOfSzSafe, CbOfSzaSafe,
// CbOfSzAndTermSafe, CbOfSzaAndTermSafe
//
// Purpose: Count the bytes required to hold a string. The string
// may be NULL in which case zero is returned.
//
// Arguments:
// psz [in] String to return count of bytes for.
//
// Returns: Count of bytes required to store string.
//
// Author: shaunco 24 Mar 1997
//
// Notes: 'AndTerm' variants includes space for the null-terminator.
//
ULONG CbOfSzSafe ( IN PCWSTR psz) { return (psz) ? CbOfSz(psz) : 0; }
ULONG CbOfSzaSafe ( IN PCSTR psza) { return (psza) ? CbOfSza(psza) : 0; }
ULONG CbOfSzAndTermSafe ( IN PCWSTR psz) { return (psz) ? CbOfSzAndTerm(psz) : 0; }
ULONG CbOfSzaAndTermSafe ( IN PCSTR psza) { return (psza) ? CbOfSzaAndTerm(psza) : 0; }
ULONG CchOfSzSafe ( IN PCWSTR psz) { return (psz) ? wcslen(psz) : 0; }
//+---------------------------------------------------------------------------
//
// Function: DwFormatString
//
// Purpose: Uses FormatMessage to format a string from variable arguments.
// The string is formatted into a fixed-size buffer the caller
// provides.
// See the description of FormatMessage in the Win32 API.
//
// Arguments:
// pszFmt [in] pointer to format string
// pszBuf [out] pointer to formatted output
// cchBuf [in] count of characters in pszBuf
// ... [in] replaceable string parameters
//
// Returns: the return value of FormatMessage
//
// Author: shaunco 15 Apr 1997
//
// Notes: The variable arguments must be strings otherwise
// FormatMessage will barf.
//
DWORD WINAPIV DwFormatString ( IN PCWSTR pszFmt, OUT PWSTR pszBuf, IN DWORD cchBuf, IN ...) { Assert (pszFmt);
va_list val; va_start(val, cchBuf); DWORD dwRet = FormatMessage (FORMAT_MESSAGE_FROM_STRING, pszFmt, 0, 0, pszBuf, cchBuf, &val); va_end(val); return dwRet; }
//+---------------------------------------------------------------------------
//
// Function: DwFormatStringWithLocalAlloc
//
// Purpose: Uses FormatMessage to format a string from variable arguments.
// The string is allocated by FormatMessage using LocalAlloc.
// See the description of FormatMessage in the Win32 API.
//
// Arguments:
// pszFmt [in] pointer to format string
// ppszBuf [out] the returned formatted string
// ... [in] replaceable string parameters
//
// Returns: the return value of FormatMessage
//
// Author: shaunco 3 May 1997
//
// Notes: The variable arguments must be strings otherwise
// FormatMessage will barf.
//
DWORD WINAPIV DwFormatStringWithLocalAlloc ( IN PCWSTR pszFmt, OUT PWSTR* ppszBuf, IN ...) { Assert (pszFmt);
va_list val; va_start(val, ppszBuf); DWORD dwRet = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFmt, 0, 0, (PWSTR)ppszBuf, 0, &val); va_end(val); return dwRet; }
//+--------------------------------------------------------------------------
//
// Function: FFindStringInCommaSeparatedList
//
// Purpose: Given a comma separated list, pszList, and a search string,
// pszSubString, this routine will try to locate pszSubString
// in the list,
//
// Arguments:
// pszSubString [in] The string to search for
// pszList [in] The list to search in
// eIgnoreSpaces [in] If NC_IGNORE, skip leading and trailing spaces
// when comparing.
// If NC_DONT_IGNORE, don't skip leading and
// trailing spaces.
// dwPosition [out] Optional. If found, the position of the first
// occurrence of the substring in the list. The first
// position is 0.
//
// Returns: BOOL. TRUE if pszSubString is in pszList, FALSE otherwise
//
// Author: billbe 09 Sep 1997
//
// Notes:
//
BOOL FFindStringInCommaSeparatedList ( IN PCWSTR pszSubString, IN PCWSTR pszList, IN NC_IGNORE_SPACES eIgnoreSpaces, OUT DWORD* pdwPosition) {
Assert(pszSubString); Assert(pszList);
int cchSubString = lstrlenW (pszSubString); int cchList = lstrlenW (pszList);
BOOL fFound = FALSE; PCWSTR pszTemp = pszList; int nIndex; const WCHAR c_chDelim = L',';
// Initialize out param if specified.
if (pdwPosition) { *pdwPosition = 0; }
// This routine searches the list for a substring matching pszSubString
// If found, checks are made to ensure the substring is not part of
// a larger substring. We continue until we find the substring or we
// have searched through the entire list.
//
while (!fFound) { // Search for the next occurence of the substring.
if (pszTemp = wcsstr (pszTemp, pszSubString)) { // we found an occurrence, so now we make sure it is not part of
// a larger string.
//
fFound = TRUE; nIndex = (int)(pszTemp - pszList);
// If the substring was not found at the beginning of the list
// we check the previous character to ensure it is the delimiter.
if (nIndex > 0) { int cchSubtract = 1;
// If we are to ignore leading spaces, find the first
// non-space character if there is one.
//
if (NC_IGNORE == eIgnoreSpaces) { // Keep skipping leading spaces until we either find a
// non-space or pass the beginning of the list.
while ((L' ' == *(pszTemp - cchSubtract)) && cchSubtract <= nIndex) { cchSubtract--; } }
// If we haven't passed the beginning of the list, compare the
// character.
if (cchSubtract <= nIndex) { fFound = (*(pszTemp - cchSubtract) == c_chDelim); } }
// If the end of the substring is not the end of the list
// we check the character after the substring to ensure
// it is a delimiter.
if (fFound && ((nIndex + cchSubString) < cchList)) { int cchAdd = cchSubString;
// If we are ignoring white spaces, we have to check the next
// available non-space character
//
if (NC_IGNORE == eIgnoreSpaces) { // Search for a non-space until we find one or pass
// the end of the list
while ((L' ' == *(pszTemp + cchAdd)) && (cchAdd + nIndex) < cchList) { cchAdd++; } }
// If we haven't passed the end of the list, check the
// character
if (nIndex + cchAdd < cchList) { fFound = (*(pszTemp + cchSubString) == c_chDelim); }
if (NC_IGNORE == eIgnoreSpaces) { // advance pointer the number of white spaces we skipped
// so we won't check those characters on the next pass
Assert(cchAdd >= cchSubString); pszTemp += (cchAdd - cchSubString); } }
// At this point, if the checks worked out, we found our string
// and will be exiting the loop
//
// Advance the temp pointer the length of the sub string we are
// searching for so we can search the rest of the list
// if we need to
pszTemp += cchSubString; } else { // Search string wasn't found
break; } }
// If we found the string and the out param exists,
// then we need to return the strings position in the list.
//
if (fFound && pdwPosition) { // We will use the number of delimters found before the string
// as an indicator of the strings position.
//
// Start at the beginning
pszTemp = pszList; PWSTR pszDelim;
// The string is nIndex characters in the list so lets get
// its correct address.
PCWSTR pszFoundString = pszList + nIndex;
// As long as we keep finding a delimiter in the list...
while (pszDelim = wcschr(pszTemp, c_chDelim)) { // If the delimiter we just found is before our string...
if (pszDelim < pszFoundString) { // Increase our position indicator
++(*pdwPosition);
// Move the temp pointer to the next string
pszTemp = pszDelim + 1;
continue; }
// The delimiter we just found is located after our
// found string so get out of the loop.
break; } }
return fFound; }
//+---------------------------------------------------------------------------
//
// Function: FIsSubstr
//
// Purpose: Case *insensitive* substring search.
//
// Arguments:
// pszSubString [in] Substring to look for.
// pszString [in] String to search in.
//
// Returns: TRUE if substring was found, FALSE otherwise.
//
// Author: danielwe 25 Feb 1997
//
// Notes: Allocates temp buffers on stack so they do not need to be
// freed.
//
BOOL FIsSubstr ( IN PCWSTR pszSubString, IN PCWSTR pszString) { PWSTR pszStringUpper; PWSTR pszSubStringUpper;
Assert(pszString); Assert(pszSubString);
#ifndef STACK_ALLOC_DOESNT_WORK
pszStringUpper = (PWSTR) (PvAllocOnStack (CbOfSzAndTerm(pszString)));
pszSubStringUpper = (PWSTR) (PvAllocOnStack (CbOfSzAndTerm(pszSubString))); #else
pszStringUpper = MemAlloc(CbOfSzAndTerm(pszString)); pszSubStringUpper = MemAlloc(CbOfSzAndTerm(pszSubString)); #endif
lstrcpyW (pszStringUpper, pszString); lstrcpyW (pszSubStringUpper, pszSubString);
// Convert both strings to uppercase before calling strstr
CharUpper (pszStringUpper); CharUpper (pszSubStringUpper);
#ifndef STACK_ALLOC_DOESNT_WORK
return NULL != wcsstr(pszStringUpper, pszSubStringUpper); #else
BOOL fRet = (NULL != wcsstr (pszStringUpper, pszSubStringUpper)); MemFree(pszStringUpper); MemFree(pszSubStringUpper);
return fRet; #endif
}
//+---------------------------------------------------------------------------
//
// Function: HrRegAddStringToDelimitedSz
//
// Purpose: Add a string into a REG_MULTI_SZ registry value.
//
// Arguments:
// pszAddString [in] The string to add to the delimited psz.
// pszIn [in] The delimited psz list.
// chDelimiter [in] The character to be used to delimit the
// values. Most multi-valued REG_SZ strings are
// delimited with either ',' or ' '. This will
// be used to delimit the value that we add,
// as well.
// dwFlags [in] Can contain one or more of the following
// values:
//
// STRING_FLAG_ALLOW_DUPLICATES
// Don't remove duplicate values when adding
// the string to the list. Default is to
// remove all other instance of this string.
// STRING_FLAG_ENSURE_AT_FRONT
// Insert the string as the first element of
// the list.
// STRING_FLAG_ENSURE_AT_END
// Insert the string as the last
// element of the list. This can not be used
// with STRING_FLAG_ENSURE_AT_FRONT.
// STRING_FLAG_ENSURE_AT_INDEX
// Ensure that the string is at dwStringIndex
// in the psz. If the index specified
// is greater than the number of strings
// in the psz, the string will be
// placed at the end.
// dwStringIndex [in] If STRING_FLAG_ENSURE_AT_INDEX is specified,
// this is the index for the string position.
// Otherwise, this value is ignored.
// pmszOut [out] The new delimited psz.
//
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: jeffspr 27 Mar 1997
//
// Modified: BillBe 9 Nov 1998
// (Extracted from HrRegAddStringToSz and modified)
//
//
// Note:
// Might want to allow for the removal of leading/trailing spaces
//
HRESULT HrAddStringToDelimitedSz ( IN PCWSTR pszAddString, IN PCWSTR pszIn, IN WCHAR chDelimiter, IN DWORD dwFlags, IN DWORD dwStringIndex, OUT PWSTR* ppszOut) { Assert(pszAddString); Assert(ppszOut);
HRESULT hr = S_OK;
// Don't continue if the pointers are NULL
if (!pszAddString || !ppszOut) { hr = E_POINTER; }
if (S_OK == hr) { // Initialize out param
*ppszOut = NULL; }
BOOL fEnsureAtFront = dwFlags & STRING_FLAG_ENSURE_AT_FRONT; BOOL fEnsureAtEnd = dwFlags & STRING_FLAG_ENSURE_AT_END; BOOL fEnsureAtIndex = dwFlags & STRING_FLAG_ENSURE_AT_INDEX;
// Can't specify more than one of these flags
if ((fEnsureAtFront && fEnsureAtEnd) || (fEnsureAtFront && fEnsureAtIndex) || (fEnsureAtEnd && fEnsureAtIndex)) { AssertSz(FALSE, "Invalid flags in HrAddStringToSz"); hr = E_INVALIDARG; }
// Have to specify at least one of these
if (!fEnsureAtFront && !fEnsureAtEnd && !fEnsureAtIndex) { AssertSz(FALSE, "Must specify a STRING_FLAG_ENSURE flag"); hr = E_INVALIDARG; }
if (S_OK == hr) { // Alloc the new blob, including enough space for the trailing comma
//
*ppszOut = (PWSTR) MemAlloc (CbOfSzAndTermSafe(pszIn) + CbOfSzSafe(pszAddString) + sizeof(WCHAR));
if (!*ppszOut) { hr = E_OUTOFMEMORY; } }
if (S_OK == hr) { DWORD dwCurrentIndex = 0; // Current index in the new buffer
// Prime the new string
//
(*ppszOut)[0] = L'\0';
// If we have the "ensure at front" flag, do so with the passed in
// value. We also do this if we have the ensure at index flag
// set with index of 0 or if the ensure at index is set but
// the input string is null or empty
//
if (fEnsureAtFront || (fEnsureAtIndex && (0 == dwStringIndex)) || (fEnsureAtIndex && (!pszIn || !*pszIn))) { lstrcpyW (*ppszOut, pszAddString); ++dwCurrentIndex; }
// If there was a previous value, walk through it and copy as needed.
// If not, then we're done.
if (pszIn && *pszIn) { PCWSTR pszCurrent = pszIn;
// Loop through the old buffer, and copy all of the strings that
// are not identical to our insertion string.
//
// Find the first string's end (at the delimiter).
PCWSTR pszEnd = wcschr (pszCurrent, chDelimiter);
while (*pszCurrent) { // If the delimiter didn't exist, set the end to the end of the
// entire string
//
if (!pszEnd) { pszEnd = pszCurrent + lstrlenW (pszCurrent); }
LONG lLength = lstrlenW (*ppszOut); if (fEnsureAtIndex && (dwCurrentIndex == dwStringIndex)) { // We know we are not at the first item since
// this would mean dwStringIndex is 0 and we would
// have copied the string before this point
//
(*ppszOut)[lLength++] = chDelimiter; (*ppszOut)[lLength++] = L'\0';
// Append the string.
lstrcatW (*ppszOut, pszAddString); ++dwCurrentIndex; } else { DWORD cch = (DWORD)(pszEnd - pszCurrent); // If we are allowing duplicates or the current string
// doesn't match the string we want to add, then we will
// copy it.
//
if ((dwFlags & STRING_FLAG_ALLOW_DUPLICATES) || (_wcsnicmp (pszCurrent, pszAddString, cch) != 0)) { // If we're not the first item, then add the delimiter.
//
if (lLength > 0) { (*ppszOut)[lLength++] = chDelimiter; (*ppszOut)[lLength++] = L'\0'; }
// Append the string.
wcsncat (*ppszOut, pszCurrent, cch); ++dwCurrentIndex; }
// Advance the pointer to one past the end of the current
// string unless, the end is not the delimiter but NULL.
// In that case, set the current point to equal the end
// pointer
//
pszCurrent = pszEnd + (*pszEnd ? 1 : 0);
// If the current pointer is not at the end of the input
// string, then find the next delimiter
//
if (*pszCurrent) { pszEnd = wcschr (pszCurrent, chDelimiter); } } } }
// If we don't have the "insert at front" flag, then we should insert
// at the end (this is the same as having the
// STRING_FLAG_ENSURE_AT_END flag set)
//
if (fEnsureAtEnd || (fEnsureAtIndex && (dwCurrentIndex <= dwStringIndex))) { LONG lLength = lstrlenW (*ppszOut);
// If we're not the first item, add the delimiter.
//
if (lstrlenW (*ppszOut) > 0) { (*ppszOut)[lLength++] = chDelimiter; (*ppszOut)[lLength++] = L'\0'; }
// Append the string.
//
lstrcatW (*ppszOut, pszAddString); } }
TraceError ("HrAddStringToDelimitedSz", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrRegRemoveStringFromDelimitedSz
//
// Purpose: Removes a string from a delimited string value
//
// Arguments:
// pszRemove [in] The string to be removed from the multi-sz
// pszIn [in] The delimited list to scan for pszRemove
// cDelimiter [in] The character to be used to delimit the
// values. Most multi-valued REG_SZ strings are
// delimited with either ',' or ' '.
// dwFlags [in] Can contain one or more of the following
// values:
//
// STRING_FLAG_REMOVE_SINGLE
// Don't remove more than one value, if
// multiple are present.
// STRING_FLAG_REMOVE_ALL
// If multiple matching values are present,
// remove them all.
// ppszOut [out] The string with pszRemove removed. Note
// that the output parameter is always set even
// if pszRemove did not exist in the list.
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: jeffspr 27 Mar 1997
//
// Modified: BillBe 10 Nov 1998
// (Extracted from HrRegAddStringToSz and modified)
//
//
//
// Note:
// Might want to allow for the removal of leading/trailing spaces
//
HRESULT HrRemoveStringFromDelimitedSz( IN PCWSTR pszRemove, IN PCWSTR pszIn, IN WCHAR chDelimiter, IN DWORD dwFlags, OUT PWSTR* ppszOut) {
Assert(pszIn && *pszIn); Assert(ppszOut);
HRESULT hr = S_OK;
// If the out param is not specified, get out
if (!ppszOut) { return E_INVALIDARG; }
// Alloc the new blob
//
hr = E_OUTOFMEMORY; *ppszOut = (PWSTR) MemAlloc (CbOfSzAndTermSafe (pszIn));
if (*ppszOut) { hr = S_OK; // Prime the new string
//
(*ppszOut)[0] = L'\0';
// If there was a previous value, walk through it and copy as needed.
// If not, then we're done
//
if (pszIn) { // Loop through the old buffer, and copy all of the strings that
// are not identical to our insertion string.
//
PCWSTR pszCurrent = pszIn;
// Loop through the old buffer, and copy all of the strings that
// are not identical to our insertion string.
//
// Find the first string's end (at the delimiter).
PCWSTR pszEnd = wcschr (pszCurrent, chDelimiter);
// Keep track of how many instances have been removed.
DWORD dwNumRemoved = 0;
while (*pszCurrent) { // If the delimiter didn't exist, set the end to the end of
// the entire string.
//
if (!pszEnd) { pszEnd = pszCurrent + lstrlenW (pszCurrent); }
DWORD cch = (DWORD)(pszEnd - pszCurrent); INT iCompare; // If we have a match, and we want to remove it (meaning that
// if we have the remove-single set, that we haven't removed
// one already).
iCompare = _wcsnicmp (pszCurrent, pszRemove, cch);
if ((iCompare) || ((dwFlags & STRING_FLAG_REMOVE_SINGLE) && (dwNumRemoved > 0))) { LONG lLength = lstrlenW (*ppszOut);
// If we're not the first item, then add the delimiter.
//
if (lLength > 0) { (*ppszOut)[lLength++] = chDelimiter; (*ppszOut)[lLength++] = L'\0'; }
// Append the string.
wcsncat (*ppszOut, pszCurrent, cch); } else { dwNumRemoved++; }
// Advance the pointer to one past the end of the current
// string unless, the end is not the delimiter but NULL.
// In that case, set the current point to equal the end
// pointer
//
pszCurrent = pszEnd + (*pszEnd ? 1 : 0);
// If the current pointer is not at the end of the input
// string, then find the next delimiter
//
if (*pszCurrent) { pszEnd = wcschr (pszCurrent, chDelimiter); } } } }
TraceError("HrRemoveStringFromDelimitedSz", hr); return hr; }
PWSTR PszAllocateAndCopyPsz ( IN PCWSTR pszSrc) { if (!pszSrc) { return NULL; }
ULONG cb = (wcslen (pszSrc) + 1) * sizeof(WCHAR); PWSTR psz = (PWSTR)MemAlloc (cb); if (psz) { CopyMemory (psz, pszSrc, cb); }
return psz; }
//+---------------------------------------------------------------------------
//
// Function: SzLoadStringPcch
//
// Purpose: Load a resource string. (This function will never return NULL.)
//
// Arguments:
// hinst [in] Instance handle of module with the string resource.
// unId [in] Resource ID of the string to load.
// pcch [out] Pointer to returned character length.
//
// Returns: Pointer to the constant string.
//
// Author: shaunco 24 Mar 1997
//
// Notes: The loaded string is pointer directly into the read-only
// resource section. Any attempt to write through this pointer
// will generate an access violation.
//
// The implementations is referenced from "Win32 Binary Resource
// Formats" (MSDN) 4.8 String Table Resources
//
// User must have RCOPTIONS = -N turned on in your sources file.
//
PCWSTR SzLoadStringPcch ( IN HINSTANCE hinst, IN UINT unId, OUT int* pcch) { Assert(hinst); Assert(unId); Assert(pcch);
static const WCHAR c_szSpace[] = L" ";
PCWSTR psz = c_szSpace; int cch = 1;
// String Tables are broken up into 16 string segments. Find the segment
// containing the string we are interested in.
HRSRC hrsrcInfo = FindResource (hinst, (PWSTR)ULongToPtr( ((LONG)(((USHORT)unId >> 4) + 1)) ), RT_STRING); if (hrsrcInfo) { // Page the resource segment into memory.
HGLOBAL hglbSeg = LoadResource (hinst, hrsrcInfo); if (hglbSeg) { // Lock the resource.
psz = (PCWSTR)LockResource(hglbSeg); if (psz) { // Move past the other strings in this segment.
// (16 strings in a segment -> & 0x0F)
unId &= 0x0F;
cch = 0; do { psz += cch; // Step to start of next string
cch = *((WCHAR*)psz++); // PASCAL like string count
} while (unId--);
// If we have a non-zero count, it includes the
// null-terminiator. Subtract this off for the return value.
//
if (cch) { cch--; } else { AssertSz(0, "String resource not found"); psz = c_szSpace; cch = 1; } } else { psz = c_szSpace; cch = 1; TraceLastWin32Error("SzLoadStringPcch: LockResource failed."); } } else TraceLastWin32Error("SzLoadStringPcch: LoadResource failed."); } else TraceLastWin32Error("SzLoadStringPcch: FindResource failed.");
*pcch = cch; Assert(*pcch); Assert(psz); return psz; }
//+---------------------------------------------------------------------------
//
// Function: SzaDupSza
//
// Purpose: Duplicates a string
//
// Arguments:
// pszaSrc [in] string to be duplicated
//
// Returns: Pointer to the new copy of the string
//
// Author: CWill 25 Mar 1997
//
// Notes: The string return must be freed (MemFree).
//
PSTR SzaDupSza ( PCSTR pszaSrc) { AssertSz(pszaSrc, "Invalid source string");
PSTR pszaDst; pszaDst = (PSTR) MemAlloc (CbOfSzaAndTerm(pszaSrc));
if(pszaDst) lstrcpyA(pszaDst, pszaSrc);
return pszaDst; }
//+---------------------------------------------------------------------------
//
// Function: SzDupSz
//
// Purpose: Duplicates a string
//
// Arguments:
// pszSrc [in] string to be duplicated
//
// Returns: Pointer to the new copy of the string
//
// Author: CWill 25 Mar 1997
//
// Notes: The string return must be freed.
//
PWSTR SzDupSz ( IN PCWSTR pszSrc) { AssertSz(pszSrc, "Invalid source string");
PWSTR pszDst; pszDst = (PWSTR) MemAlloc (CbOfSzAndTerm(pszSrc)); if(pszDst) lstrcpyW (pszDst, pszSrc);
return pszDst; }
BOOL FSubstringMatch ( PCTSTR pStr1, PCTSTR pStr2, const WCHAR** ppStart, ULONG* pcch) { const WCHAR* p1Start; const WCHAR* p1End; const WCHAR* p2Start; const WCHAR* p2End; ULONG cch1; ULONG cch2;
if (ppStart) { *ppStart = NULL; } if (pcch) { *pcch = NULL; }
p1End = pStr1; while (1) { GetNextCommaSeparatedToken(p1Start, p1End, cch1); if (!cch1) { break; }
p2End = pStr2; while (1) { GetNextCommaSeparatedToken(p2Start, p2End, cch2); if (!cch2) { break; }
if (cch1 == cch2) { if (0 == memcmp(p1Start, p2Start, cch1 * sizeof(WCHAR))) { if (ppStart) { *ppStart = p1Start; } if (pcch) { *pcch = cch1; }
return TRUE; } } } }
return FALSE; }
VOID DeleteColString ( list<tstring*>* pcolstr) { Assert( pcolstr );
list<tstring*>::const_iterator iter; tstring* pstr;
for (iter = pcolstr->begin(); iter != pcolstr->end(); iter++) { pstr = *iter; delete pstr; } pcolstr->erase( pcolstr->begin(), pcolstr->end() ); }
VOID DeleteColString ( vector<tstring*>* pcolstr) { Assert( pcolstr );
vector<tstring*>::const_iterator iter; tstring* pstr;
for (iter = pcolstr->begin(); iter != pcolstr->end(); iter++) { pstr = *iter; delete pstr; } pcolstr->erase( pcolstr->begin(), pcolstr->end() ); }
|