Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

870 lines
15 KiB

/*++
Copyright (C) 2000 Microsoft Corporation
All rights reserved.
Module Name:
string.cxx
Abstract:
String class
Author:
Steve Kiraly (SteveKi) 03-Mar-2000
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "string.hxx"
//
// Class specific NULL state.
//
TCHAR TString::gszNullState[2] = {0,0};
/*++
Routine Name:
Default constructor
Routine Description:
Initialize the string class to a valid state.
Arguments:
None
Return Value:
None, Use IsValid to determine success or failure.
--*/
TString::
TString(
VOID
) : m_pszString(&TString::gszNullState[kValid])
{
}
/*++
Routine Name:
Non trivial constructor
Routine Description:
Construction using an existing LPCTSTR string.
Arguments:
psz - pointer to string
Return Value:
None, Use IsValid to determine success or failure.
--*/
TString::
TString(
IN LPCTSTR psz
) : m_pszString(&TString::gszNullState[kValid])
{
if (FAILED(Update(psz)))
{
m_pszString = &TString::gszNullState[kInValid];
}
}
/*++
Routine Name:
Copy constructor.
Routine Description:
Creates a copy of a string from another string object
Arguments:
String - refrence to existing string
Return Value:
None, Use IsValid to determine success or failure.
--*/
TString::
TString(
IN const TString &String
) : m_pszString(&TString::gszNullState[kValid])
{
if (FAILED(Update(String.m_pszString)))
{
m_pszString = &TString::gszNullState[kInValid];
}
}
/*++
Routine Name:
Destructor
Routine Description:
Destruction, ensure we don't free our NULL state.
Arguments:
None.
Return Value:
None.
--*/
TString::
~TString(
VOID
)
{
vFree(m_pszString);
}
/*++
Routine Name:
bEmpty
Routine Description:
Indicates if a string has any usable data.
Arguments:
None.
Return Value:
TRUE string has data, FALSE string has no data.
--*/
BOOL
TString::
bEmpty(
VOID
) const
{
return m_pszString[0] == 0;
}
/*++
Routine Name:
IsValid
Routine Description:
Indicates if a string object is valid.
Arguments:
None.
Return Value:
An HRESULT
--*/
HRESULT
TString::
IsValid(
VOID
) const
{
return m_pszString != &TString::gszNullState[kInValid] ? S_OK : E_OUTOFMEMORY;
}
/*++
Routine Name:
uLen
Routine Description:
Return the length of the string in characters not including
the NULL terminator.
Arguments:
None.
Return Value:
Length of the string in characters not including the NULL terminator.
--*/
UINT
TString::
uLen(
VOID
) const
{
return _tcslen(m_pszString);
}
/*++
Routine Name:
Cat
Routine Description:
Safe concatenation of the specified string to the string
object. If the allocation fails this routine will return a
failure and the orginal string will be un touched. If the
passed in string pointer is null or the passed in string
points to the null string the function succeeds and does
not update the string.
Arguments:
psz - Input string, may be NULL.
Return Value:
An HRESULT
--*/
HRESULT
TString::
Cat(
IN LPCTSTR psz
)
{
HRESULT hStatus = S_OK;
size_t cchSize = 0;
LPTSTR pszDst = NULL;
LPTSTR pszTmp = NULL;
size_t cchRemaining = 0;
//
// Silently ignore a null string pointer or the empty string.
//
if (psz && *psz)
{
//
// Calculate new buffer size consisting of the size of the orginal
// string plus the sizeof of the new string plus the null terminator.
//
cchSize = _tcslen(m_pszString) + _tcslen(psz) + 1;
//
// Allocate the new buffer.
//
pszTmp = new TCHAR[cchSize];
//
// If memory was not available.
//
hStatus = pszTmp ? S_OK : E_OUTOFMEMORY;
//
// Copy the current string to the temp buffer.
//
if (SUCCEEDED(hStatus))
{
hStatus = StringCchCopyEx(pszTmp, cchSize, m_pszString, &pszDst, &cchRemaining, 0);
}
//
// Concatenate the new string on the end of the temp buffer.
//
if (SUCCEEDED(hStatus))
{
hStatus = StringCchCopy(pszDst, cchRemaining, psz);
}
//
// Release the current string buffer and assign the new concatenated
// string to the internal string pointer.
//
if (SUCCEEDED(hStatus))
{
vFree(m_pszString);
m_pszString = pszTmp;
pszTmp = NULL;
}
vFree(pszTmp);
}
return hStatus;
}
/*++
Routine Name:
Update
Routine Description:
Safe updating of string. If the allocation fails, return FALSE
and it leaves the original string untouched. If the new string is
NULL the current string is released and the class is put into a
valid state.
Arguments:
psz - Input string, may be NULL.
Return Value:
An HRESULT
--*/
HRESULT
TString::
Update(
IN LPCTSTR psz
)
{
HRESULT hRetval = S_OK;
LPTSTR pszTmp = NULL;
size_t cchSize = 0;
//
// Validate the passed in pointer.
//
if (psz)
{
//
// Calculate the new string size including the null terminator.
//
cchSize = _tcslen(psz) + 1;
//
// Create temp pointer and allocate the new string.
//
pszTmp = new TCHAR [cchSize];
hRetval = pszTmp ? S_OK : E_OUTOFMEMORY;
//
// Copy the string
//
if (SUCCEEDED(hRetval))
{
hRetval = StringCchCopy(pszTmp, cchSize, psz);
}
//
// Release the old string and save the new string in the class pointer.
//
if (SUCCEEDED(hRetval))
{
vFree(m_pszString);
m_pszString = pszTmp;
pszTmp = NULL;
}
vFree(pszTmp);
}
else
{
//
// Release the current string.
//
vFree(m_pszString);
//
// Mark the object as valid.
//
m_pszString = &TString::gszNullState[kValid];
}
return hRetval;
}
/*++
Routine Name:
LoadStringFromRC
Routine Description:
Safe load of a string from a resources file.
Arguments:
hInst - Instance handle of resource file.
uId - Resource id to load.
Return Value:
An HRESULT
--*/
HRESULT
TString::
LoadStringFromRC(
IN HINSTANCE hInst,
IN UINT uID
)
{
LPTSTR pszString = NULL;
INT iSize = 0;
INT iLen = 0;
HRESULT hResult = E_FAIL;
//
// Continue increasing the buffer until
// the buffer is big enough to hold the entire string.
//
for (iSize = kStrMax; ; iSize += kStrMax)
{
//
// Allocate string buffer.
//
pszString = new TCHAR [iSize];
if (pszString)
{
iLen = ::LoadString(hInst, uID, pszString, iSize);
if(iLen == 0)
{
delete [] pszString;
hResult = E_FAIL;
break;
}
//
// Since LoadString does not indicate if the string was truncated or it
// just happened to fit. When we detect this ambiguous case we will
// try one more time just to be sure.
//
else if (iSize - iLen <= 1)
{
delete [] pszString;
}
//
// LoadString was successful release original string buffer
// and update new buffer pointer.
//
else
{
vFree(m_pszString);
m_pszString = pszString;
hResult = S_OK;
break;
}
}
else
{
hResult = E_OUTOFMEMORY;
break;
}
}
return hResult;
}
/*++
Routine Name:
vFree
Routine Description:
Safe free, frees the string memory. Ensures
we do not try an free our global memory block.
Arguments:
pszString - pointer to string meory to free.
Return Value:
Nothing.
--*/
VOID
TString::
vFree(
IN LPTSTR pszString
)
{
//
// If this memory was not pointing to our
// class specific gszNullStates then release the memory.
//
if (pszString != &TString::gszNullState[kValid] &&
pszString != &TString::gszNullState[kInValid])
{
delete [] pszString;
}
}
/*++
Routine Name:
Format
Routine Description:
Format the string opbject similar to sprintf.
Arguments:
pszFmt - pointer format string.
.. - variable number of arguments similar to sprintf.
Return Value:
An HRESULT S_OK if string was format successfully. E_XXX if error
occurred creating the format string.
--*/
HRESULT
WINAPIV
TString::
Format(
IN LPCTSTR pszFmt,
IN ...
)
{
HRESULT hStatus = E_FAIL;
va_list pArgs;
va_start(pArgs, pszFmt);
hStatus = vFormat(pszFmt, pArgs);
va_end(pArgs);
return hStatus;
}
/*++
Routine Name:
vFormat
Routine Description:
Format the string opbject similar to vsprintf.
Arguments:
pszFmt pointer format string.
pointer to variable number of arguments similar to vsprintf.
Return Value:
An HRESULT - S_OK if string was format successfully. E_XXX if error
occurred creating the format string.
--*/
HRESULT
TString::
vFormat(
IN LPCTSTR pszFmt,
IN va_list avlist
)
{
//
// Format the string.
//
LPTSTR pszTemp = vsntprintf(pszFmt, avlist);
//
// If format succeeded, release the old string and save the
// new formated string.
//
HRESULT hStatus = pszTemp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hStatus))
{
//
// Release the old string.
//
vFree(m_pszString);
//
// Save pointer to new string.
//
m_pszString = pszTemp;
}
return hStatus;
}
/*++
Routine Name:
vsntprintf
Routine Description:
//
// Formats a string and returns a heap allocated string with the
// formated data. This routine can be used to for extremely
// long format strings. Note: If a valid pointer is returned
// the callng functions must release the data with a call to delete.
// Example:
//
// LPCTSTR p = vsntprintf("Test %s", pString );
//
// SetTitle( p );
//
// delete [] p;
//
Arguments:
pszString pointer format string.
pointer to a variable number of arguments.
Return Value:
Pointer to format string. NULL if error.
--*/
LPTSTR
TString::
vsntprintf(
IN LPCTSTR szFmt,
IN va_list pArgs
)
{
LPTSTR pszBuff = NULL;
INT iSize = kStrIncrement;
for( ; ; )
{
//
// Allocate the message buffer.
//
pszBuff = new TCHAR [iSize];
if (!pszBuff)
{
break;
}
//
// If the string was formatted then exit.
//
if (SUCCEEDED(StringCchVPrintf(pszBuff, iSize, szFmt, pArgs)))
{
break;
}
//
// String did not fit release the current buffer.
//
if (pszBuff)
{
delete [] pszBuff;
}
//
// Double the buffer size after each failure.
//
iSize *= 2;
//
// If the size is greater than 100k exit without formatting a string.
//
if (iSize > kStrMaxFormatSize)
{
pszBuff = NULL;
break;
}
}
return pszBuff;
}
/*++
Routine Name:
FormatMsg
Routine Description:
This function formats a message string using the windows
api FormatMessage, hence it will deal with the %1 %2 insertion
specifiers.
Arguments:
pszFmt - Pointer to format string, see the SDK under FormatMessage for
all possible format specifiers.
.. - variable number of arguments
Return Value:
An HRESULT
--*/
HRESULT
WINAPIV
TString::
FormatMsg(
IN LPCTSTR pszFmt,
IN ...
)
{
LPTSTR pszRet = NULL;
DWORD dwBytes = 0;
HRESULT hRetval = E_FAIL;
va_list pArgs;
//
// Point to the first un-named argument.
//
va_start(pArgs, pszFmt);
//
// Format the message.
//
dwBytes = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
pszFmt,
0,
0,
reinterpret_cast<LPWSTR>(&pszRet),
0,
&pArgs);
va_end(pArgs);
//
// If the number of bytes is non zero the API formatted the
// string.
//
if (dwBytes)
{
//
// Update the return string object.
//
hRetval = Update(pszRet);
//
// Release the formated string.
//
if (pszRet)
{
LocalFree(pszRet);
}
}
else
{
hRetval = HRESULT_FROM_WIN32(GetLastError());
}
return hRetval;
}
/*++
Routine Name:
ToUpper
Routine Description:
modifies the current string to be all uppercase
Arguments:
none
Return Value:
none
--*/
VOID
TString::
ToUpper(
VOID
)
{
if (m_pszString != &TString::gszNullState[kValid] &&
m_pszString != &TString::gszNullState[kInValid])
{
UINT Len = _tcslen(m_pszString);
for (UINT i = 0; i < Len; i++)
{
m_pszString[i] = towupper(m_pszString[i]);
}
}
}
/*++
Routine Name:
ToLower
Routine Description:
modifies the current string to be all lowercase
Arguments:
none
Return Value:
none
--*/
VOID
TString::
ToLower(
VOID
)
{
if (m_pszString != &TString::gszNullState[kValid] &&
m_pszString != &TString::gszNullState[kInValid])
{
UINT Len = _tcslen(m_pszString);
for (UINT i = 0; i < Len; i++)
{
m_pszString[i] = towlower(m_pszString[i]);
}
}
}