// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. #pragma once #include "buffer.h" #include class STRU { public: STRU( VOID ); STRU( __inout_ecount(cchInit) WCHAR* pbInit, __in DWORD cchInit ); BOOL IsEmpty( VOID ) const; BOOL Equals( __in const STRU * pstrRhs, __in BOOL fIgnoreCase = FALSE ) const { _ASSERTE( pstrRhs != NULL ); return Equals( pstrRhs->QueryStr(), fIgnoreCase ); } BOOL Equals( __in const STRU & strRhs, __in BOOL fIgnoreCase = FALSE ) const { return Equals( strRhs.QueryStr(), fIgnoreCase ); } BOOL Equals( __in PCWSTR pszRhs, __in BOOL fIgnoreCase = FALSE ) const { _ASSERTE( NULL != pszRhs ); if ( NULL == pszRhs ) { return FALSE; } #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN return ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(), QueryCCH(), pszRhs, -1, fIgnoreCase ) ); #else if( fIgnoreCase ) { return ( 0 == _wcsicmp( QueryStr(), pszRhs ) ); } return ( 0 == wcscmp( QueryStr(), pszRhs ) ); #endif } static BOOL Equals( __in PCWSTR pwszLhs, __in PCWSTR pwszRhs, __in bool fIgnoreCase = false ) { // Return FALSE if either or both strings are NULL. if (!pwszLhs || !pwszRhs) return FALSE; // // This method performs a ordinal string comparison when OS is Vista or // greater and a culture sensitive comparison if not (XP). This is // consistent with the existing Equals implementation (see above). // #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN return ( CSTR_EQUAL == CompareStringOrdinal( pwszLhs, -1, pwszRhs, -1, fIgnoreCase ) ); #else if( fIgnoreCase ) { return ( 0 == _wcsicmp( pwszLhs, pwszRhs ) ); } else { return ( 0 == wcscmp( pwszLhs, pwszRhs ) ); } #endif } VOID Trim(); BOOL StartsWith( __in const STRU * pStruPrefix, __in bool fIgnoreCase = FALSE ) const { _ASSERTE( pStruPrefix != NULL ); return StartsWith( pStruPrefix->QueryStr(), fIgnoreCase ); } BOOL StartsWith( __in const STRU & struPrefix, __in bool fIgnoreCase = FALSE ) const { return StartsWith( struPrefix.QueryStr(), fIgnoreCase ); } BOOL StartsWith( __in PCWSTR pwszPrefix, __in bool fIgnoreCase = FALSE ) const; BOOL EndsWith( __in const STRU * pStruSuffix, __in bool fIgnoreCase = FALSE ) const { _ASSERTE( pStruSuffix != NULL ); return EndsWith( pStruSuffix->QueryStr(), fIgnoreCase ); } BOOL EndsWith( __in const STRU & struSuffix, __in bool fIgnoreCase = FALSE ) const { return EndsWith( struSuffix.QueryStr(), fIgnoreCase ); } BOOL EndsWith( __in PCWSTR pwszSuffix, __in bool fIgnoreCase = FALSE ) const; INT IndexOf( __in WCHAR charValue, __in DWORD dwStartIndex = 0 ) const; INT IndexOf( __in PCWSTR pwszValue, __in DWORD dwStartIndex = 0 ) const; INT LastIndexOf( __in WCHAR charValue, __in DWORD dwStartIndex = 0 ) const; DWORD QueryCB( VOID ) const; DWORD QueryCCH( VOID ) const; DWORD QuerySizeCCH( VOID ) const; __nullterminated __ecount(this->m_cchLen) WCHAR* QueryStr( VOID ) const; VOID Reset( VOID ); HRESULT Resize( DWORD cchSize ); HRESULT SyncWithBuffer( VOID ); template HRESULT Copy( __in PCWSTR const (&rgpszStrings)[size] ) // // Copies an array of strings declared as stack array. For example: // // LPCWSTR rgExample[] { L"one", L"two" }; // hr = str.Copy( rgExample ); // { Reset(); return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); } HRESULT Copy( __in PCWSTR pszCopy ); HRESULT Copy( __in_ecount(cchLen) PCWSTR pszCopy, SIZE_T cchLen ); HRESULT Copy( __in const STRU * pstrRhs ); HRESULT Copy( __in const STRU & str ); HRESULT CopyAndExpandEnvironmentStrings( __in PCWSTR pszSource ); HRESULT CopyA( __in PCSTR pszCopyA ); HRESULT CopyA( __in_bcount(cchLen) PCSTR pszCopyA, SIZE_T cchLen, UINT CodePage = CP_UTF8 ); template HRESULT Append( __in PCWSTR const (&rgpszStrings)[size] ) // // Appends an array of strings declared as stack array. For example: // // LPCWSTR rgExample[] { L"one", L"two" }; // hr = str.Append( rgExample ); // { return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); } HRESULT Append( __in PCWSTR pszAppend ); HRESULT Append( __in_ecount(cchLen) PCWSTR pszAppend, SIZE_T cchLen ); HRESULT Append( __in const STRU * pstrRhs ); HRESULT Append( __in const STRU & strRhs ); HRESULT AppendA( __in PCSTR pszAppendA ); HRESULT AppendA( __in_bcount(cchLen) PCSTR pszAppendA, SIZE_T cchLen, UINT CodePage = CP_UTF8 ); HRESULT CopyToBuffer( __out_bcount(*pcb) WCHAR* pszBuffer, PDWORD pcb ) const; HRESULT SetLen( __in DWORD cchLen ); HRESULT SafeSnwprintf( __in PCWSTR pwszFormatString, ... ); HRESULT SafeVsnwprintf( __in PCWSTR pwszFormatString, va_list argsList ); static HRESULT ExpandEnvironmentVariables( __in PCWSTR pszString, __out STRU * pstrExpandedString ); private: // // Avoid C++ errors. This object should never go through a copy // constructor, unintended cast or assignment. // STRU( const STRU & ); STRU & operator = ( const STRU & ); HRESULT AuxAppend( __in_ecount(cNumStrings) PCWSTR const rgpszStrings[], SIZE_T cNumStrings ); HRESULT AuxAppend( __in_bcount(cbStr) const WCHAR* pStr, SIZE_T cbStr, DWORD cbOffset ); HRESULT AuxAppendA( __in_bcount(cbStr) const CHAR* pStr, SIZE_T cbStr, DWORD cbOffset, UINT CodePage ); // // Buffer with an inline buffer of 1, // enough to hold null-terminating character. // BUFFER_T m_Buff; DWORD m_cchLen; }; // // Helps to initialize an external buffer before // constructing the STRU object. // template WCHAR* InitHelper(__out WCHAR (&psz)[size]) { psz[0] = L'\0'; return psz; } // // Heap operation reduction macros // #define STACK_STRU(name, size) WCHAR __ach##name[size];\ STRU name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) #define INLINE_STRU(name, size) WCHAR __ach##name[size];\ STRU name; #define INLINE_STRU_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) HRESULT MakePathCanonicalizationProof( IN PCWSTR pszName, OUT STRU * pstrPath );