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.
661 lines
12 KiB
661 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
icstring.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains ICSTRING class methods. Split from ICSTRING.HXX (inline methods)
|
|
|
|
Contents:
|
|
ICSTRING::ICSTRING(ICSTRING&)
|
|
ICSTRING::~ICSTRING()
|
|
ICSTRING::operator=(LPSTR)
|
|
ICSTRING::operator=(ICSTRING&)
|
|
ICSTRING::operator+=(LPSTR)
|
|
ICSTRING::operator+=(char)
|
|
ICSTRING::strncat(LPVOID, DWORD)
|
|
ICSTRING::CreateStringBuffer(LPVOID, DWORD, DWORD)
|
|
ICSTRING::CreateOffsetString(DWORD, DWORD)
|
|
ICSTRING::CopyTo(LPSTR)
|
|
ICSTRING::CopyTo(LPSTR, LPSTR)
|
|
ICSTRING::CopyTo(LPSTR, DWORD)
|
|
ICSTRING::CopyTo(LPSTR, LPDWORD)
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 18-Dec-1995
|
|
|
|
Revision History:
|
|
|
|
18-Dec-1995 rfirth
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <wininetp.h>
|
|
|
|
//
|
|
// methods
|
|
//
|
|
|
|
//
|
|
//ICSTRING::ICSTRING(
|
|
// IN ICSTRING& String
|
|
// )
|
|
//
|
|
///*++
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// copy constructor. We now create an entirely new string (used to be just a
|
|
// reference of the rvalue)
|
|
//
|
|
//Arguments:
|
|
//
|
|
// String - to copy
|
|
//
|
|
//Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--*/
|
|
//
|
|
//{
|
|
// //
|
|
// // can't already have string in lvalue, & rvalue mustn't be an offset string
|
|
// //
|
|
//
|
|
// INET_ASSERT(!HaveString());
|
|
// INET_ASSERT(!String.IsOffset());
|
|
// INET_ASSERT(!String.IsError());
|
|
//
|
|
// *this = String.StringAddress();
|
|
//}
|
|
|
|
|
|
ICSTRING::~ICSTRING(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
destructor
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// can only free the string if it is not a reference. Offset type
|
|
// implies reference
|
|
//
|
|
|
|
if (!IsReference() && (_String != NULL)) {
|
|
|
|
INET_ASSERT(!IsOffset());
|
|
|
|
(VOID)ResizeBuffer((HLOCAL)_String, 0, FALSE);
|
|
_String = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
ICSTRING&
|
|
ICSTRING::operator=(
|
|
IN LPSTR String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy/assigment. Copies a string to this object. If NULL, frees up the
|
|
current buffer
|
|
|
|
Arguments:
|
|
|
|
String - to be assigned
|
|
|
|
Return Value:
|
|
|
|
ICSTRING&
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// if this is an offset string then there's not much to do
|
|
//
|
|
|
|
if (IsOffset()) {
|
|
Initialize();
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
// string MUST NOT be a copy (we'll free the real string pointer, owned
|
|
// by another object) and SHOULD NOT be copied itself (the objects with
|
|
// copies of the string will potentially have a bad pointer)
|
|
//
|
|
|
|
INET_ASSERT((String == NULL) ? TRUE : !IsReference());
|
|
INET_ASSERT(!IsReferenced());
|
|
|
|
//
|
|
// if the pointer is NULL or the string is empty then we are freeing the
|
|
// string pointer
|
|
//
|
|
|
|
DWORD len;
|
|
|
|
if (String == NULL) {
|
|
len = 0;
|
|
} else {
|
|
len = ::strlen(String);
|
|
if (len != 0) {
|
|
INET_ASSERT(len < 0xffffffff);
|
|
++len;
|
|
}
|
|
}
|
|
|
|
//
|
|
// free or grow the buffer, depending on requirements
|
|
//
|
|
|
|
if ((len > _BufferLength) || ((len == 0) && (_String != NULL))) {
|
|
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, len, FALSE);
|
|
_BufferLength = (_String != NULL) ? len : 0;
|
|
}
|
|
if (_String != NULL) {
|
|
|
|
INET_ASSERT(len != 0);
|
|
|
|
memcpy((LPVOID)_String, (LPVOID)String, len);
|
|
_StringLength = len - 1;
|
|
SetHaveString(TRUE);
|
|
SetError(FALSE);
|
|
} else {
|
|
_StringLength = 0;
|
|
SetHaveString(FALSE);
|
|
SetError(len != 0); // an error might have occurred
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
ICSTRING&
|
|
ICSTRING::operator=(
|
|
IN ICSTRING& String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy/assignment. Makes new copy of object (used to just make a reference)
|
|
|
|
Arguments:
|
|
|
|
String - ICSTRING object to be assigned
|
|
|
|
Return Value:
|
|
|
|
ICSTRING&
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(!IsReferenced());
|
|
INET_ASSERT(!String.IsReferenced());
|
|
INET_ASSERT(!String.IsError());
|
|
|
|
//
|
|
// if we're copying an offset, make sure that any string we may already
|
|
// have is freed
|
|
//
|
|
|
|
if (String.IsOffset()) {
|
|
if (_String != NULL) {
|
|
ResizeBuffer(_String, 0, FALSE);
|
|
}
|
|
_String = String._String;
|
|
_StringLength = String._StringLength;
|
|
_BufferLength = String._BufferLength;
|
|
_Union.Dword = String._Union.Dword;
|
|
} else {
|
|
|
|
INET_ASSERT(!IsOffset() && !String.IsOffset());
|
|
|
|
//
|
|
// use string assignment to correctly setup this object
|
|
//
|
|
|
|
*this = String.StringAddress();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::operator+=(
|
|
IN LPSTR String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Concatenates a string to the buffer. Reallocates it if necessary. String
|
|
CANNOT be NULL
|
|
|
|
Arguments:
|
|
|
|
String - to concatenate
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(!IsReference());
|
|
INET_ASSERT(!IsReferenced());
|
|
INET_ASSERT(!IsOffset());
|
|
INET_ASSERT(String != NULL);
|
|
|
|
if (IsError()) {
|
|
return;
|
|
}
|
|
|
|
if (*String == '\0') {
|
|
return;
|
|
}
|
|
|
|
DWORD len = ::strlen(String);
|
|
DWORD newlen = _StringLength + len + 1;
|
|
|
|
INET_ASSERT ((newlen > _StringLength) && (newlen > len));
|
|
|
|
if (_BufferLength < newlen) {
|
|
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
|
|
|
|
INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
|
|
|
|
_BufferLength = newlen;
|
|
}
|
|
if (_String != NULL) {
|
|
memcpy((LPVOID)((LPBYTE)_String + _StringLength),
|
|
(LPVOID)String,
|
|
len + 1
|
|
);
|
|
_StringLength += len;
|
|
} else {
|
|
_StringLength = 0;
|
|
_BufferLength = 0;
|
|
SetError(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::operator+=(
|
|
IN char Ch
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Concatenates a character to the buffer. Reallocates it if necessary. Ch
|
|
CAN be '\0'
|
|
|
|
Arguments:
|
|
|
|
Ch - to concatenate
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(!IsReference());
|
|
INET_ASSERT(!IsReferenced());
|
|
INET_ASSERT(!IsOffset());
|
|
|
|
if (IsError()) {
|
|
return;
|
|
}
|
|
|
|
DWORD newlen = _StringLength + 2;
|
|
|
|
INET_ASSERT (newlen > _StringLength);
|
|
|
|
if (_BufferLength < newlen) {
|
|
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
|
|
|
|
INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
|
|
|
|
_BufferLength = newlen;
|
|
}
|
|
if (_String != NULL) {
|
|
_String[_StringLength] = Ch;
|
|
++_StringLength;
|
|
_String[_StringLength] = '\0';
|
|
} else {
|
|
_StringLength = 0;
|
|
_BufferLength = 0;
|
|
SetError(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::Strncat(
|
|
IN LPVOID Pointer,
|
|
IN DWORD Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies Length characters from Pointer to the end of _String
|
|
|
|
Arguments:
|
|
|
|
Pointer - place to copy from
|
|
|
|
Length - number of characters to copy
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (IsError()) {
|
|
return;
|
|
}
|
|
|
|
INET_ASSERT(Pointer != NULL);
|
|
INET_ASSERT(Length != 0);
|
|
INET_ASSERT(_String != NULL);
|
|
INET_ASSERT(!IsReference());
|
|
INET_ASSERT(!IsReferenced());
|
|
|
|
DWORD newLength;
|
|
|
|
newLength = _StringLength + Length + 1;
|
|
|
|
INET_ASSERT ((newLength > _StringLength) && (newLength > Length));
|
|
|
|
if (_BufferLength < newLength) {
|
|
_String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE);
|
|
_BufferLength = newLength;
|
|
}
|
|
if (_String != NULL) {
|
|
memcpy((LPVOID)&_String[_StringLength], Pointer, Length);
|
|
_StringLength += Length;
|
|
|
|
INET_ASSERT(_StringLength < _BufferLength);
|
|
|
|
_String[_StringLength] = '\0';
|
|
} else {
|
|
_StringLength = 0;
|
|
_BufferLength = 0;
|
|
SetError(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CreateStringBuffer(
|
|
IN LPVOID Pointer,
|
|
IN DWORD StringLength,
|
|
IN DWORD BufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
In order to avoid reallocations, if we know the size of the buffer we
|
|
want for several strcat()'s, e.g., we can allocate it once, copy the
|
|
initial string here, then perform multiple concatenate operations (+=)
|
|
|
|
Arguments:
|
|
|
|
Pointer - place to start copying from
|
|
|
|
StringLength - length of string
|
|
|
|
BufferLength - length of buffer required
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(Pointer != NULL);
|
|
INET_ASSERT(BufferLength > StringLength);
|
|
INET_ASSERT(BufferLength != 0);
|
|
|
|
//
|
|
// if we currently have an offset string then initialize to a non-offset
|
|
//
|
|
|
|
if (IsOffset()) {
|
|
Initialize();
|
|
}
|
|
_String = (LPSTR)ResizeBuffer(_String, BufferLength, FALSE);
|
|
if (_String != NULL) {
|
|
_StringLength = StringLength;
|
|
_BufferLength = BufferLength;
|
|
memcpy((LPVOID)_String, Pointer, _StringLength);
|
|
_String[_StringLength] = '\0';
|
|
SetHaveString(TRUE);
|
|
SetReference(FALSE);
|
|
SetReferenced(FALSE);
|
|
SetOffset(FALSE);
|
|
SetError(FALSE);
|
|
} else {
|
|
SetError(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CreateOffsetString(
|
|
IN DWORD Offset,
|
|
IN DWORD Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a reference ICSTRING that is an offset within another buffer
|
|
|
|
Arguments:
|
|
|
|
Offset - offset into buffer
|
|
|
|
Length - of string
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
_String = (LPSTR)(DWORD_PTR)Offset;
|
|
_StringLength = Length;
|
|
_BufferLength = Length;
|
|
ZapFlags();
|
|
SetHaveString(TRUE); // ICSTRING initialized with non-NULL
|
|
SetReference(TRUE); // reference to another string buffer
|
|
SetOffset(TRUE); // offset from base
|
|
SetError(FALSE);
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CopyTo(
|
|
IN LPSTR Buffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies source _String to destination Buffer
|
|
|
|
Arguments:
|
|
|
|
Buffer - place to copy to
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(Buffer != NULL);
|
|
INET_ASSERT(!IsOffset());
|
|
|
|
memcpy((LPVOID)Buffer, (LPVOID)_String, _StringLength);
|
|
Buffer[_StringLength] = '\0';
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CopyTo(
|
|
IN LPSTR Base,
|
|
IN LPSTR Buffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies a based (offset) string from source Base + _String to destination
|
|
Buffer
|
|
|
|
Arguments:
|
|
|
|
Base - value for base
|
|
|
|
Buffer - place to write string
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(Buffer != NULL);
|
|
//INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
|
|
|
|
memcpy((LPVOID)Buffer,
|
|
IsOffset() ? (Base + (DWORD_PTR)_String) : _String,
|
|
_StringLength
|
|
);
|
|
Buffer[_StringLength] = '\0';
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CopyTo(
|
|
IN LPSTR Buffer,
|
|
IN DWORD Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies at most Length characters from source _String to destination
|
|
Buffer
|
|
|
|
Arguments:
|
|
|
|
Buffer - place to write string
|
|
|
|
Length - number of characters to copy
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(Buffer != NULL);
|
|
INET_ASSERT(!IsOffset());
|
|
|
|
DWORD length = min(Length - 1, _StringLength);
|
|
|
|
memcpy((LPVOID)Buffer, (LPVOID)_String, length);
|
|
Buffer[length] = '\0';
|
|
}
|
|
|
|
|
|
VOID
|
|
ICSTRING::CopyTo(
|
|
IN LPSTR Buffer,
|
|
IN OUT LPDWORD Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies at most *Length characters from source _String to destination
|
|
Buffer. Updates *Length to be number of characters copied, not including
|
|
terminating NUL
|
|
|
|
Arguments:
|
|
|
|
Buffer - place to write string
|
|
|
|
Length - IN: length of buffer
|
|
OUT: number of characters copied
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INET_ASSERT(Buffer != NULL);
|
|
INET_ASSERT(!IsOffset());
|
|
|
|
DWORD length = min(*Length - 1, _StringLength);
|
|
|
|
memcpy((LPVOID)Buffer, (LPVOID)_String, length);
|
|
Buffer[length] = '\0';
|
|
*Length = length;
|
|
}
|