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.
225 lines
6.4 KiB
225 lines
6.4 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1994 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
multisz.hxx
|
|
|
|
This module contains a light weight multi-string class
|
|
|
|
|
|
FILE HISTORY:
|
|
KeithMo 20-Jan-1997 Created from string.hxx.
|
|
*/
|
|
|
|
|
|
#ifndef _MULTISZ_HXX_
|
|
#define _MULTISZ_HXX_
|
|
|
|
# include <string.hxx>
|
|
|
|
|
|
/*++
|
|
class MULTISZ:
|
|
|
|
Intention:
|
|
A light-weight multi-string class supporting encapsulated string class.
|
|
|
|
This object is derived from BUFFER class.
|
|
It maintains following state:
|
|
|
|
m_fValid - whether this object is valid -
|
|
used only by MULTISZ() init functions
|
|
* NYI: I need to kill this someday *
|
|
m_cchLen - string length cached when we update the string.
|
|
m_cStrings - number of strings.
|
|
|
|
Member Functions:
|
|
There are two categories of functions:
|
|
1) Safe Functions - which do integrity checking of state
|
|
2) UnSafe Functions - which do not do integrity checking, but
|
|
enable writing to the data stream freely.
|
|
(someday this will be enabled as Safe versions without
|
|
problem for users)
|
|
|
|
--*/
|
|
class IRTL_DLLEXP MULTISZ : public BUFFER
|
|
{
|
|
public:
|
|
|
|
MULTISZ()
|
|
: BUFFER (),
|
|
m_cchLen ( 0),
|
|
m_cStrings(0)
|
|
{ Reset(); }
|
|
|
|
// creates a stack version of the MULTISZ object - uses passed in stack buffer
|
|
// MULTISZ does not free this pbInit on its own.
|
|
MULTISZ( WCHAR * pbInit, DWORD cbInit)
|
|
: BUFFER( (BYTE *) pbInit, cbInit),
|
|
m_cchLen (0),
|
|
m_cStrings(0)
|
|
{}
|
|
|
|
MULTISZ( const WCHAR * pchInit )
|
|
: BUFFER (),
|
|
m_cchLen ( 0),
|
|
m_cStrings(0)
|
|
{ AuxInit(pchInit); }
|
|
|
|
MULTISZ( const MULTISZ & str )
|
|
: BUFFER (),
|
|
m_cchLen ( 0),
|
|
m_cStrings(0)
|
|
{ AuxInit( str.QueryStr()); }
|
|
|
|
BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
|
|
//
|
|
// Checks and returns TRUE if this string has no valid data else FALSE
|
|
//
|
|
BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); }
|
|
|
|
BOOL Append( const WCHAR * pchInit ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
(DWORD) (::wcslen(pchInit) + 1) * sizeof(WCHAR)
|
|
)) :
|
|
TRUE);
|
|
}
|
|
|
|
|
|
BOOL Append( const WCHAR * pchInit, DWORD cchLen ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
cchLen * sizeof(WCHAR))) :
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Append( STRU & str )
|
|
{ return AuxAppend( str.QueryStr(),
|
|
(str.QueryCCH() + 1) * sizeof(WCHAR)); }
|
|
|
|
// Resets the internal string to be NULL string. Buffer remains cached.
|
|
VOID Reset( VOID)
|
|
{ DBG_ASSERT( QueryPtr() != NULL);
|
|
QueryStr()[0] = L'\0';
|
|
QueryStr()[1] = L'\0';
|
|
m_cchLen = 2;
|
|
m_cStrings = 0;
|
|
}
|
|
|
|
BOOL Copy( const WCHAR * pchInit, IN DWORD cbLen ) {
|
|
if ( QueryPtr() ) { Reset(); }
|
|
return ( (pchInit != NULL) ?
|
|
AuxAppend( pchInit, cbLen, FALSE ):
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Copy( const MULTISZ & str )
|
|
{ return ( Copy(str.QueryStr(), str.QueryCB())); }
|
|
|
|
//
|
|
// Returns the number of bytes in the string including the terminating
|
|
// NULLs
|
|
//
|
|
UINT QueryCB( VOID ) const
|
|
{ return ( m_cchLen * sizeof(WCHAR)); }
|
|
|
|
//
|
|
// Returns # of characters in the string including the terminating NULLs
|
|
//
|
|
UINT QueryCCH( VOID ) const { return (m_cchLen); }
|
|
|
|
//
|
|
// Returns # of strings in the multisz.
|
|
//
|
|
|
|
DWORD QueryStringCount( VOID ) const { return m_cStrings; }
|
|
|
|
//
|
|
// Makes a copy of the stored string in given buffer
|
|
//
|
|
BOOL CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcch) const;
|
|
|
|
//
|
|
// Return the string buffer
|
|
//
|
|
WCHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
|
|
WCHAR * QueryStr( VOID ) const { return ((WCHAR *) QueryPtr()); }
|
|
|
|
//
|
|
// Makes a clone of the current string in the string pointer passed in.
|
|
//
|
|
BOOL
|
|
Clone( OUT MULTISZ * pstrClone) const
|
|
{
|
|
return ((pstrClone == NULL) ?
|
|
(SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
|
|
(pstrClone->Copy( *this))
|
|
);
|
|
} // MULTISZ::Clone()
|
|
|
|
//
|
|
// Recalculates the length of *this because we've modified the buffers
|
|
// directly
|
|
//
|
|
|
|
VOID RecalcLen( VOID )
|
|
{ m_cchLen = MULTISZ::CalcLength( QueryStr(), &m_cStrings ); }
|
|
|
|
//
|
|
// Calculate total character length of a MULTI_SZ, including the
|
|
// terminating NULLs.
|
|
//
|
|
|
|
static DWORD CalcLength( const WCHAR * str,
|
|
LPDWORD pcStrings = NULL );
|
|
|
|
//
|
|
// Determine if the MULTISZ contains a specific string.
|
|
//
|
|
|
|
BOOL FindString( const WCHAR * str );
|
|
|
|
BOOL FindString( STRU & str )
|
|
{ return FindString( str.QueryStr() ); }
|
|
|
|
//
|
|
// Determine if the MULTISZ contains a specific string - case-insensitive
|
|
//
|
|
|
|
BOOL FindStringNoCase( const WCHAR * str );
|
|
|
|
BOOL FindStringNoCase( STRU & str )
|
|
{ return FindStringNoCase( str.QueryStr() ); }
|
|
|
|
//
|
|
// Used for scanning a multisz.
|
|
//
|
|
|
|
const WCHAR * First( VOID ) const
|
|
{ return *QueryStr() == L'\0' ? NULL : QueryStr(); }
|
|
|
|
const WCHAR * Next( const WCHAR * Current ) const
|
|
{ Current += ::wcslen( Current ) + 1;
|
|
return *Current == L'\0' ? NULL : Current; }
|
|
|
|
private:
|
|
|
|
DWORD m_cchLen;
|
|
DWORD m_cStrings;
|
|
VOID AuxInit( const WCHAR * pInit );
|
|
BOOL AuxAppend( const WCHAR * pInit,
|
|
UINT cbStr, BOOL fAddSlop = TRUE );
|
|
|
|
};
|
|
|
|
//
|
|
// Quick macro for declaring a MULTISZ that will use stack memory of <size>
|
|
// bytes. If the buffer overflows then a heap buffer will be allocated
|
|
//
|
|
|
|
#define STACK_MULTISZ( name, size ) WCHAR __ach##name[size]; \
|
|
MULTISZ name( __ach##name, sizeof( __ach##name ))
|
|
|
|
#endif // !_MULTISZ_HXX_
|
|
|