|
|
//+---------------------------------------------------------------------------
//
// 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"
#include "ncmsz.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 CbOfTSzSafe ( IN PCTSTR psza) { return (psza) ? CbOfTSz(psza) : 0; }
ULONG CbOfSzAndTermSafe ( IN PCWSTR psz) { return (psz) ? CbOfSzAndTerm(psz) : 0; }
ULONG CbOfSzaAndTermSafe ( IN PCSTR psza) { return (psza) ? CbOfSzaAndTerm(psza) : 0; }
ULONG CbOfTSzAndTermSafe ( IN PCTSTR psza) { return (psza) ? CbOfTSzAndTerm(psza) : 0; }
ULONG CchOfSzSafe ( IN PCTSTR psz) { return (psz) ? _tcslen(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 = FormatMessageW (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 = FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFmt, 0, 0, (PWSTR)ppszBuf, 0, &val); va_end(val); return dwRet; }
PWSTR WszAllocateAndCopyWsz ( 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: WszLoadStringPcch
//
// 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 WszLoadStringPcch ( 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.
// See KB ID: Q20011 for a half-explanation of the second argument below.
HRSRC hrsrcInfo = FindResource (hinst, (PTSTR)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) { strcpy(pszaDst, pszaSrc); }
return pszaDst; }
//+---------------------------------------------------------------------------
//
// Function: TszDupTsz
//
// Purpose: Duplicates a string
//
// Arguments:
// pszSrc [in] string to be duplicated
//
// Returns: Pointer to the new copy of the string
//
// Notes: The string return must be freed.
//
PTSTR TszDupTsz ( IN PCTSTR pszSrc) { AssertSz(pszSrc, "Invalid source string");
PTSTR pszDst; pszDst = (PTSTR) MemAlloc (CbOfTSzAndTermSafe(pszSrc)); if (pszDst) { _tcscpy(pszDst, pszSrc); }
return pszDst; }
//+---------------------------------------------------------------------------
//
// Function: WszDupWsz
//
// Purpose: Duplicates a wide string
//
// Arguments:
// szOld [in] String to duplicate
//
// Returns: Newly allocated copy
//
// Author: danielwe 4 Aug 2000
//
// Notes: Caller must free result with delete []
//
LPWSTR WszDupWsz(LPCWSTR szOld) { LPWSTR szNew;
szNew = new WCHAR[lstrlen(szOld) + 1]; if (szNew) { lstrcpy(szNew, szOld); }
return szNew; }
LPWSTR WszFromSz(LPCSTR szAnsi) { Assert(szAnsi);
LPWSTR pszResult; LPWSTR pszWide; INT cchWide; INT result;
pszResult = NULL;
if (!szAnsi) { goto Cleanup; }
result = ::MultiByteToWideChar(CP_ACP, 0, szAnsi, -1, NULL, 0); if (!result) { TraceLastWin32Error("WszFromSz: MultiByteToWideChar #1"); goto Cleanup; }
cchWide = result;
pszWide = new WCHAR [ cchWide ]; if (!pszWide) { TraceError("WszFromSz: new", E_OUTOFMEMORY); goto Cleanup; }
result = ::MultiByteToWideChar(CP_ACP, 0, szAnsi, -1, pszWide, cchWide); if (!result) { TraceLastWin32Error("WszFromSz: MultiByteToWideChar #2");
delete [] pszWide; goto Cleanup; }
pszResult = pszWide;
Cleanup: return pszResult; }
LPWSTR WszFromUtf8(LPCSTR szUtf8) { Assert(szUtf8);
LPWSTR pszResult; LPWSTR pszWide; INT cchWide; INT result;
pszResult = NULL;
if (!szUtf8) { goto Cleanup; }
result = ::MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, NULL, 0); if (!result) { TraceLastWin32Error("WszFromUtf8: MultiByteToWideChar #1"); goto Cleanup; }
cchWide = result;
pszWide = new WCHAR [ cchWide ]; if (!pszWide) { TraceError("WszFromUtf8: new", E_OUTOFMEMORY); goto Cleanup; }
result = ::MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, pszWide, cchWide); if (!result) { TraceLastWin32Error("WszFromUtf8: MultiByteToWideChar #2");
delete [] pszWide; goto Cleanup; }
pszResult = pszWide;
Cleanup: return pszResult; }
LPSTR SzFromWsz(LPCWSTR szWide) { Assert(szWide);
LPSTR pszResult; LPSTR pszAnsi; INT cbAnsi; INT result;
pszResult = NULL;
if (!szWide) { goto Cleanup; }
result = ::WideCharToMultiByte(CP_ACP, 0, szWide, -1, NULL, 0, NULL, NULL); if (!result) { TraceLastWin32Error("SzFromWsz: WideCharToMultiByte #1"); goto Cleanup; }
cbAnsi = result;
pszAnsi = (CHAR *)MemAlloc(cbAnsi); if (!pszAnsi) { TraceError("SzFromWsz: MemAlloc", E_OUTOFMEMORY); goto Cleanup; }
result = ::WideCharToMultiByte(CP_ACP, 0, szWide, -1, pszAnsi, cbAnsi, NULL, NULL); if (!result) { TraceLastWin32Error("SzFromWsz: WideCharToMultiByte #2");
MemFree(pszAnsi); goto Cleanup; }
pszResult = pszAnsi;
Cleanup: return pszResult; }
LPSTR Utf8FromWsz(LPCWSTR szWide) { Assert(szWide);
LPSTR pszResult; LPSTR pszUtf8; INT cbUtf8; INT result;
pszResult = NULL;
if (!szWide) { goto Cleanup; }
result = ::WideCharToMultiByte(CP_UTF8, 0, szWide, -1, NULL, 0, NULL, NULL); if (!result) { TraceLastWin32Error("Utf8FromWsz: WideCharToMultiByte #1"); goto Cleanup; }
cbUtf8 = result;
pszUtf8 = (CHAR *)MemAlloc(cbUtf8); if (!pszUtf8) { TraceError("SzFromWsz: MemAlloc", E_OUTOFMEMORY); goto Cleanup; }
result = ::WideCharToMultiByte(CP_UTF8, 0, szWide, -1, pszUtf8, cbUtf8, NULL, NULL); if (!result) { TraceLastWin32Error("Utf8FromWsz: WideCharToMultiByte #2");
MemFree(pszUtf8); goto Cleanup; }
pszResult = pszUtf8;
Cleanup: return pszResult; }
LPWSTR WszFromTsz(LPCTSTR pszInputString) { #ifdef _UNICODE
return WszAllocateAndCopyWsz(pszInputString); #else // not unicode
return WszFromSz(pszInputString); #endif // _UNICODE
}
LPTSTR TszFromWsz(LPCWSTR pszInputString) { #ifdef _UNICODE
return WszAllocateAndCopyWsz(pszInputString); #else // not unicode
return SzFromWsz(pszInputString); #endif // _UNICODE
}
LPTSTR TszFromSz(LPCSTR szAnsi) { #ifdef _UNICODE
return WszFromSz(szAnsi); #else
return SzaDupSza(szAnsi); #endif
}
LPSTR SzFromTsz(LPCTSTR pszInputString) { #ifdef _UNICODE
return SzFromWsz(pszInputString); #else
return SzaDupSza(pszInputString); #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 PCTSTR pszAddString, IN PCTSTR pszIn, IN TCHAR chDelimiter, IN DWORD dwFlags, IN DWORD dwStringIndex, OUT PTSTR* 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 = (PTSTR) MemAlloc (CbOfTSzAndTermSafe(pszIn) + CbOfTSzSafe(pszAddString) + sizeof(TCHAR));
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))) { _tcscpy (*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) { PCTSTR 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).
PCTSTR pszEnd = _tcschr (pszCurrent, chDelimiter);
while (*pszCurrent) { // If the delimiter didn't exist, set the end to the end of the
// entire string
//
if (!pszEnd) { pszEnd = pszCurrent + _tcslen (pszCurrent); }
LONG lLength = _tcslen (*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.
_tcscat (*ppszOut, pszAddString); ++dwCurrentIndex; } else { DWORD_PTR cch = 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) || (_tcsnicmp (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.
_tcsncat (*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 = _tcschr (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 = _tcslen (*ppszOut);
// If we're not the first item, add the delimiter.
//
if (_tcslen (*ppszOut) > 0) { (*ppszOut)[lLength++] = chDelimiter; (*ppszOut)[lLength++] = L'\0'; }
// Append the string.
//
_tcscat (*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 PCTSTR pszRemove, IN PCTSTR pszIn, IN TCHAR chDelimiter, IN DWORD dwFlags, OUT PTSTR* 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 = (PTSTR) MemAlloc (CbOfTSzAndTermSafe (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.
//
PCTSTR 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).
PCTSTR pszEnd = _tcschr (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 + _tcslen (pszCurrent); }
DWORD_PTR cch = 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 = _tcsnicmp (pszCurrent, pszRemove, cch);
if ((iCompare) || ((dwFlags & STRING_FLAG_REMOVE_SINGLE) && (dwNumRemoved > 0))) { LONG lLength = _tcslen (*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.
_tcsncat (*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 = _tcschr (pszCurrent, chDelimiter); } } } }
TraceError("HrRemoveStringFromDelimitedSz", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrReallocAndCopyString
//
// Purpose: Copies a given string into a string pointer that might
// already contain an alloc()ed string. If the destination
// pointer contains a string (e.g. is non-null), that string
// is freed before the copy occurs.
//
// Arguments:
// pszSrc The string to copy. This may be NULL.
// ppszDest The address of the pointer which will contain the copied
// string. If *ppszDest is non-NULL when the function is
// called, its value will be freed before the string is
// copied. On return, it will contain a copy of pszSrc,
// or be set to NULL (if pszSrc is NULL).
//
// Returns: TRUE if the *ppszDest was set
// E_OUTOFMEMORY if the new string could not be allocated
//
// Notes:
//
HRESULT HrReallocAndCopyString(/* IN */ LPCWSTR pszSrc, /* INOUT */ LPWSTR * ppszDest) { Assert(ppszDest);
HRESULT hr; LPWSTR pszTemp;
hr = S_OK;
pszTemp = NULL;
if (pszSrc) { // copy the string into pszTemp
pszTemp = WszAllocateAndCopyWsz(pszSrc); if (!pszTemp) { hr = E_OUTOFMEMORY; goto Cleanup; } }
if (*ppszDest) { delete [] *ppszDest; } *ppszDest = pszTemp;
Cleanup: TraceError("HrReallocAndCopyString", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrCopyString
//
// Purpose: Copies a string using new
//
// Arguments:
// szSrc [in] String to be copied
// pszDest [out] Copy
//
// Returns:
//
// Author: mbend 12 Nov 2000
//
// Notes:
//
HRESULT HrCopyString(const char * szSrc, char ** pszDest) { HRESULT hr = S_OK;
if(szSrc) { *pszDest = new char[lstrlenA(szSrc) + 1]; if(!*pszDest) { hr = E_OUTOFMEMORY; } if(SUCCEEDED(hr)) { lstrcpyA(*pszDest, szSrc); } } else { hr = E_POINTER; }
TraceHr(ttidError, FAL, hr, (hr == E_POINTER), "HrCopyString"); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrCopyString
//
// Purpose: Copies a string using new
//
// Arguments:
// szSrc [in] String to be copied
// pszDest [out] Copy
//
// Returns:
//
// Author: mbend 12 Nov 2000
//
// Notes:
//
HRESULT HrCopyString(const wchar_t * szSrc, wchar_t ** pszDest) { HRESULT hr = S_OK;
if(szSrc) { *pszDest = new wchar_t[lstrlen(szSrc) + 1]; if(!*pszDest) { hr = E_OUTOFMEMORY; } if(SUCCEEDED(hr)) { lstrcpy(*pszDest, szSrc); } } else { hr = E_POINTER; }
TraceHr(ttidError, FAL, hr, (hr == E_POINTER), "HrCopyString"); return hr; }
//
// Stol.. er. "borrowed" from \\index2\ntsrc\enduser\windows.com\wuv3\wuv3\string.cpp
//
char *stristr(const char *string1, const char *string2) { char *pSave = (char *)string1; char *ps1 = (char *)string1; char *ps2 = (char *)string2;
if ( !*ps1 || !ps2 || !ps1 ) return NULL;
if ( !*ps2 ) return ps1;
while( *ps1 ) { while( *ps2 && (toupper(*ps2) == toupper(*ps1)) ) { ps2++; ps1++; } if ( !*ps2 ) return pSave; if ( ps2 == string2 ) { ps1++; pSave = ps1; } else ps2 = (char *)string2; }
return NULL; }
|