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.

718 lines
25 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. CString.h
  5. Abstract:
  6. A CString class, pure UNICODE internally.
  7. History:
  8. 02/22/2001 robkenny Ported from MFC
  9. 08/14/2001 robkenny Inserted inside the ShimLib namespace.
  10. --*/
  11. #pragma once
  12. #include <limits.h>
  13. namespace ShimLib
  14. {
  15. // Use the standard exception handler, if this is not defined
  16. // the C++ exception handler will be used instead.
  17. //#define USE_SEH
  18. #ifndef AFXAPI
  19. #define AFXAPI __stdcall
  20. #endif
  21. #ifndef AFXISAPI
  22. #define AFXISAPI __stdcall
  23. #endif
  24. #ifndef AFXISAPI_CDECL
  25. #define AFXISAPI_CDECL __cdecl
  26. #endif
  27. #ifndef AFX_CDECL
  28. #define AFX_CDECL __cdecl
  29. #endif
  30. #ifndef AFX_INLINE
  31. #define AFX_INLINE __inline
  32. #endif
  33. #ifndef AFX_CORE_DATA
  34. #define AFX_CORE_DATA
  35. #endif
  36. #ifndef AFX_DATA
  37. #define AFX_DATA
  38. #endif
  39. #ifndef AFX_DATADEF
  40. #define AFX_DATADEF
  41. #endif
  42. #ifndef AFX_API
  43. #define AFX_API
  44. #endif
  45. #ifndef AFX_COMDAT
  46. #define AFX_COMDAT
  47. #endif
  48. #ifndef AFX_STATIC
  49. #define AFX_STATIC static
  50. #endif
  51. BOOL AFXAPI AfxIsValidString(LPCWSTR lpsz, int nLength = -1);
  52. BOOL AFXAPI AfxIsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite = TRUE);
  53. inline size_t strlenChars(const char* s1)
  54. {
  55. const char * send = s1;
  56. while (*send)
  57. {
  58. // Can't use CharNextA, since User32 might not be initialized
  59. if (IsDBCSLeadByte(*send))
  60. {
  61. ++send;
  62. }
  63. ++send;
  64. }
  65. return send - s1;
  66. }
  67. // Prototype for a string comparison routine.
  68. typedef WCHAR * (__cdecl *_pfn_wcsstr)(const WCHAR * s1, const WCHAR * s2);
  69. template <class CharType> class CStringData
  70. {
  71. public:
  72. long nRefs; // reference count
  73. int nDataLength; // length of data (including terminator) re
  74. int nAllocLength; // length of allocation
  75. // CharType data[nAllocLength]
  76. CharType* data() // CharType* to managed data
  77. { return (CharType*)(this+1); }
  78. };
  79. class CString
  80. {
  81. public:
  82. #ifdef USE_SEH
  83. // SEH Exception information
  84. enum
  85. {
  86. eCStringNoMemoryException = STATUS_NO_MEMORY,
  87. eCStringExceptionValue = 0x12345678,
  88. };
  89. static int ExceptionFilter(PEXCEPTION_POINTERS pexi);
  90. static const ULONG_PTR m_CStringExceptionValue;
  91. #else
  92. // A class used only for throwing C++ exceptions
  93. class CStringError
  94. {
  95. public:
  96. CStringError() {};
  97. ~CStringError() {};
  98. };
  99. #endif
  100. public:
  101. static WCHAR ChNil;
  102. public:
  103. // Constructors
  104. // constructs empty CString
  105. CString();
  106. // copy constructor
  107. CString(const CString & stringSrc);
  108. // from a single character
  109. CString(WCHAR ch, int nRepeat = 1);
  110. // allocate nLen WCHARs space.
  111. CString(int nLength);
  112. CString(const WCHAR * lpsz);
  113. // subset of characters from an ANSI string (converts to WCHAR)
  114. CString(const WCHAR * lpch, int nLength);
  115. // Create from an ANSI string
  116. CString(LPCSTR lpsz);
  117. CString(LPCSTR lpsz, int nCharacters);
  118. // Attributes & Operations
  119. // get data length, number of characters
  120. int GetLength() const;
  121. // TRUE if zero length
  122. BOOL IsEmpty() const;
  123. // clear contents to empty
  124. void Empty();
  125. // return pointer to const string
  126. operator const WCHAR * () const;
  127. const WCHAR * Get() const;
  128. // Get, return NULL if string is empty
  129. const WCHAR * GetNIE() const;
  130. char * GetAnsi() const;
  131. // Get ANSI string: caller is responsible for freeing the string
  132. char * ReleaseAnsi() const;
  133. // Get, return NULL if string is empty
  134. char * GetAnsiNIE() const;
  135. // return single character at zero-based index
  136. WCHAR GetAt(int nIndex) const;
  137. // return single character at zero-based index
  138. WCHAR operator[](int nIndex) const;
  139. // set a single character at zero-based index
  140. void SetAt(int nIndex, WCHAR ch);
  141. // overloaded assignment
  142. // copy string content from UNICODE string
  143. const CString & operator=(const WCHAR * lpsz);
  144. // ref-counted copy from another CString
  145. const CString & operator=(const CString & stringSrc);
  146. // set string content to single character
  147. const CString & operator=(WCHAR ch);
  148. // copy string content from unsigned chars
  149. //const CString & operator=(const unsigned WCHAR* psz);
  150. const CString& CString::operator=(LPCSTR lpsz);
  151. // string concatenation
  152. // concatenate from another CString
  153. const CString & operator+=(const CString & string);
  154. // concatenate a single character
  155. const CString & operator+=(WCHAR ch);
  156. // concatenate a string
  157. const CString & operator+=(const WCHAR * lpsz);
  158. friend CString AFXAPI operator+(const CString & string1, const CString & string2);
  159. friend CString AFXAPI operator+(const CString & string, WCHAR ch);
  160. friend CString AFXAPI operator+(WCHAR ch, const CString & string);
  161. friend CString AFXAPI operator+(const CString & string, const WCHAR * lpsz);
  162. friend CString AFXAPI operator+(const WCHAR * lpsz, const CString & string);
  163. // string comparison
  164. // straight character comparison
  165. int Compare(const WCHAR * lpsz) const;
  166. // compare ignoring case
  167. int CompareNoCase(const WCHAR * lpsz) const;
  168. // NLS aware comparison, case sensitive
  169. int Collate(const WCHAR * lpsz) const;
  170. // NLS aware comparison, case insensitive
  171. int CollateNoCase(const WCHAR * lpsz) const;
  172. int ComparePart(const WCHAR * lpsz, int start, int nChars) const;
  173. int ComparePartNoCase(const WCHAR * lpsz, int start, int nChars) const;
  174. int EndsWith(const WCHAR * lpsz) const;
  175. int EndsWithNoCase(const WCHAR * lpsz) const;
  176. // simple sub-string extraction
  177. // return nCount characters starting at zero-based nFirst
  178. CString Mid(int nFirst, int nCount) const;
  179. // return all characters starting at zero-based nFirst
  180. CString Mid(int nFirst) const;
  181. // return first nCount characters in string
  182. CString Left(int nCount) const;
  183. // return nCount characters from end of string
  184. CString Right(int nCount) const;
  185. // characters from beginning that are also in passed string
  186. CString SpanIncluding(const WCHAR * lpszCharSet) const;
  187. // characters from beginning that are not also in passed string
  188. CString SpanExcluding(const WCHAR * lpszCharSet) const;
  189. // upper/lower/reverse conversion
  190. // NLS aware conversion to uppercase
  191. void MakeUpper();
  192. // NLS aware conversion to lowercase
  193. void MakeLower();
  194. // reverse string right-to-left
  195. void MakeReverse();
  196. // trimming whitespace (either side)
  197. // remove whitespace starting from right edge
  198. void TrimRight();
  199. // remove whitespace starting from left side
  200. void TrimLeft();
  201. // trimming anything (either side)
  202. // remove continuous occurrences of chTarget starting from right
  203. void TrimRight(WCHAR chTarget);
  204. // remove continuous occcurrences of characters in passed string,
  205. // starting from right
  206. void TrimRight(const WCHAR * lpszTargets);
  207. // remove continuous occurrences of chTarget starting from left
  208. void TrimLeft(WCHAR chTarget);
  209. // remove continuous occcurrences of characters in
  210. // passed string, starting from left
  211. void TrimLeft(const WCHAR * lpszTargets);
  212. // advanced manipulation
  213. // replace occurrences of chOld with chNew
  214. int Replace(WCHAR chOld, WCHAR chNew);
  215. // replace occurrences of substring lpszOld with lpszNew;
  216. // empty lpszNew removes instances of lpszOld
  217. int Replace(const WCHAR * lpszOld, const WCHAR * lpszNew);
  218. // Case insensitive version of Replace
  219. int ReplaceI(const WCHAR * lpszOld, const WCHAR * lpszNew);
  220. // remove occurrences of chRemove
  221. int Remove(WCHAR chRemove);
  222. // insert character at zero-based index; concatenates
  223. // if index is past end of string
  224. int Insert(int nIndex, WCHAR ch);
  225. // insert substring at zero-based index; concatenates
  226. // if index is past end of string
  227. int Insert(int nIndex, const WCHAR * pstr);
  228. // delete nCount characters starting at zero-based index
  229. int Delete(int nIndex, int nCount = 1);
  230. // delete all characters to the right of nIndex
  231. void Truncate(int nIndex);
  232. // searching
  233. // find character starting at left, -1 if not found
  234. int Find(WCHAR ch) const;
  235. // find character starting at right
  236. int ReverseFind(WCHAR ch) const;
  237. // find character starting at zero-based index and going right
  238. int Find(WCHAR ch, int nStart) const;
  239. // find first instance of any character in passed string
  240. int FindOneOf(const WCHAR * lpszCharSet) const;
  241. // find first instance of any character in passed string starting at zero-based index
  242. int FindOneOf(const WCHAR * lpszCharSet, int nCount) const;
  243. // find first instance of substring
  244. int Find(const WCHAR * lpszSub) const;
  245. // find first instance of substring starting at zero-based index
  246. int Find(const WCHAR * lpszSub, int nStart) const;
  247. // find first instance of any character *not* in passed string starting at zero-based index
  248. int FindOneNotOf(const WCHAR * lpszCharSet, int nCount) const;
  249. // simple formatting
  250. // printf-like formatting using passed string
  251. void AFX_CDECL Format(const WCHAR * lpszFormat, ...);
  252. // printf-like formatting using referenced string resource
  253. //void AFX_CDECL Format(UINT nFormatID, ...);
  254. // printf-like formatting using variable arguments parameter
  255. void FormatV(const WCHAR * lpszFormat, va_list argList);
  256. // Format routines that accept ANSI args
  257. void AFX_CDECL Format(const char * lpszFormat, ...);
  258. void FormatV(const char * lpszFormat, va_list argList);
  259. // formatting for localization (uses FormatMessage API)
  260. // format using FormatMessage API on passed string
  261. void AFX_CDECL FormatMessage(const WCHAR * lpszFormat, ...);
  262. // input and output
  263. #ifdef _DEBUG
  264. friend CDumpContext& AFXAPI operator<<(CDumpContext& dc,
  265. const CString & string);
  266. #endif
  267. // friend CArchive& AFXAPI operator<<(CArchive& ar, const CString & string);
  268. // friend CArchive& AFXAPI operator>>(CArchive& ar, CString & string);
  269. // friend const CString & AFXAPI AfxGetEmptyString();
  270. // Access to string implementation buffer as "C" character array
  271. // get pointer to modifiable buffer at least as long as nMinBufLength
  272. WCHAR * GetBuffer(int nMinBufLength);
  273. // release buffer, setting length to nNewLength (or to first nul if -1)
  274. void ReleaseBuffer(int nNewLength = -1);
  275. // get pointer to modifiable buffer exactly as long as nNewLength
  276. WCHAR * GetBufferSetLength(int nNewLength);
  277. // release memory allocated to but unused by string
  278. void FreeExtra();
  279. // Use LockBuffer/UnlockBuffer to turn refcounting off
  280. // turn refcounting back on
  281. WCHAR * LockBuffer();
  282. // turn refcounting off
  283. void UnlockBuffer();
  284. // ======================================================================
  285. // CString extensions: making life easier.
  286. //
  287. // Win32 API
  288. // NOTE: The return values are different from Win32
  289. // Return 0 for failure or number of chars for success
  290. DWORD GetModuleFileNameW(HMODULE hModule);
  291. DWORD GetShortPathNameW(void);
  292. DWORD GetLongPathNameW(void);
  293. DWORD GetFullPathNameW(void);
  294. DWORD GetSystemDirectoryW(void);
  295. DWORD GetSystemWindowsDirectoryW(void);
  296. DWORD GetWindowsDirectoryW(void);
  297. DWORD GetTempPathW(void);
  298. DWORD GetTempFileNameW(LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique );
  299. DWORD ExpandEnvironmentStringsW(void);
  300. DWORD GetCurrentDirectoryW(void);
  301. DWORD GetLocaleInfoW(LCID Locale, LCTYPE LCType);
  302. // Returns NtStatus
  303. DWORD NtReqQueryValueExW(const WCHAR * lpszKey, const WCHAR * lpszValue);
  304. // Split this into the seperate path components
  305. void SplitPath(CString * csDrive, CString * csDir, CString * csName, CString * csExt) const;
  306. void MakePath(const CString * csDrive, const CString * csDir, const CString * csName, const CString * csExt);
  307. // Properly append csPath onto the end of this path
  308. void AppendPath(const WCHAR * lpszPath);
  309. // Find the trailing path component
  310. // Return index of the last path seperator or -1 if none found
  311. int FindLastPathComponent() const;
  312. // Get the "file" portion of this path
  313. void GetLastPathComponent(CString & pathComponent) const;
  314. // Get what's not the "file" portion of this path
  315. void GetNotLastPathComponent(CString & pathComponent) const;
  316. // Remove the trailing path component
  317. void StripPath();
  318. // Get the drive portion either c:\ or \\machine\
  319. // Note this is different from SplitPath
  320. void GetDrivePortion(CString & csDrivePortion) const;
  321. // Does this string match the pattern
  322. BOOL PatternMatch(const WCHAR * lpszPattern) const;
  323. BOOL IsPathSep(int index) const;
  324. // More efficient versions of above
  325. void Mid(int nFirst, int nCount, CString & csMid) const;
  326. void Mid(int nFirst, CString & csMid) const;
  327. void Left(int nCount, CString & csLeft) const;
  328. void Right(int nCount, CString & csRight) const;
  329. void SpanIncluding(const WCHAR * lpszCharSet, CString & csSpanInc) const;
  330. void SpanExcluding(const WCHAR * lpszCharSet, CString & csSpanExc) const;
  331. //
  332. // End of extensions
  333. //
  334. // ======================================================================
  335. // Implementation
  336. public:
  337. ~CString();
  338. int GetAllocLength() const;
  339. protected:
  340. WCHAR * m_pchData; // pointer to ref counted string data
  341. mutable char * m_pchDataAnsi; // pointer to non-UNICODE version of string
  342. // implementation helpers
  343. CStringData<WCHAR> * GetData() const;
  344. void Init();
  345. void AllocCopy(CString & dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
  346. void AllocBuffer(int nLen);
  347. void AssignCopy(int nSrcLen, const WCHAR * lpszSrcData);
  348. void ConcatCopy(int nSrc1Len, const WCHAR * lpszSrc1Data, int nSrc2Len, const WCHAR * lpszSrc2Data);
  349. void ConcatInPlace(int nSrcLen, const WCHAR * lpszSrcData);
  350. void CopyBeforeWrite();
  351. void AllocBeforeWrite(int nLen);
  352. void Release();
  353. //============================================================
  354. // Used by Replace and ReplaceI
  355. int ReplaceRoutine(LPCWSTR lpszOld, LPCWSTR lpszNew, _pfn_wcsstr tcsstr);
  356. static void Release(CStringData<WCHAR>* pData);
  357. static int SafeStrlen(const WCHAR * lpsz);
  358. static void FreeData(CStringData<WCHAR>* pData);
  359. static int _afxInitData[];
  360. static CStringData<WCHAR>* _afxDataNil;
  361. static const WCHAR * _afxPchNil;
  362. };
  363. /*
  364. End of class definitions.
  365. Below are routines that are candidates for inlining.
  366. */
  367. #ifdef afxEmptyString
  368. #undef afxEmptyString
  369. #endif
  370. #define afxEmptyString ((CString &)*(CString*)&CString::_afxPchNil)
  371. inline BOOL IsPathSep(WCHAR ch)
  372. {
  373. return ch == L'\\' || ch == L'/';
  374. }
  375. // Compare helpers
  376. AFX_INLINE bool AFXAPI operator==(const CString & s1, const CString & s2) { return s1.Compare(s2) == 0; }
  377. AFX_INLINE bool AFXAPI operator==(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) == 0; }
  378. AFX_INLINE bool AFXAPI operator==(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) == 0; }
  379. AFX_INLINE bool AFXAPI operator!=(const CString & s1, const CString & s2) { return s1.Compare(s2) != 0; }
  380. AFX_INLINE bool AFXAPI operator!=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) != 0; }
  381. AFX_INLINE bool AFXAPI operator!=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) != 0; }
  382. AFX_INLINE bool AFXAPI operator<(const CString & s1, const CString & s2) { return s1.Compare(s2) < 0; }
  383. AFX_INLINE bool AFXAPI operator<(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) < 0; }
  384. AFX_INLINE bool AFXAPI operator<(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) > 0; }
  385. AFX_INLINE bool AFXAPI operator>(const CString & s1, const CString & s2) { return s1.Compare(s2) > 0; }
  386. AFX_INLINE bool AFXAPI operator>(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) > 0; }
  387. AFX_INLINE bool AFXAPI operator>(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) < 0; }
  388. AFX_INLINE bool AFXAPI operator<=(const CString & s1, const CString & s2) { return s1.Compare(s2) <= 0; }
  389. AFX_INLINE bool AFXAPI operator<=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) <= 0; }
  390. AFX_INLINE bool AFXAPI operator<=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) >= 0; }
  391. AFX_INLINE bool AFXAPI operator>=(const CString & s1, const CString & s2) { return s1.Compare(s2) >= 0; }
  392. AFX_INLINE bool AFXAPI operator>=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) >= 0; }
  393. AFX_INLINE bool AFXAPI operator>=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) <= 0; }
  394. // CString
  395. AFX_INLINE CStringData<WCHAR>* CString::GetData() const { ASSERT(m_pchData != NULL, "CString::GetData: NULL m_pchData"); return ((CStringData<WCHAR>*)m_pchData)-1; }
  396. AFX_INLINE void CString::Init() { m_pchData = afxEmptyString.m_pchData; m_pchDataAnsi = NULL; }
  397. AFX_INLINE CString::CString() { Init(); }
  398. //AFX_INLINE CString::CString(const unsigned WCHAR* lpsz) { Init(); *this = (LPCSTR)lpsz; }
  399. //AFX_INLINE const CString & CString::operator=(const unsigned WCHAR* lpsz) { *this = (LPCSTR)lpsz; return *this; }
  400. AFX_INLINE int CString::GetLength() const { return GetData()->nDataLength; }
  401. AFX_INLINE int CString::GetAllocLength() const { return GetData()->nAllocLength; }
  402. AFX_INLINE BOOL CString::IsEmpty() const { return GetData()->nDataLength == 0; }
  403. AFX_INLINE CString::operator const WCHAR *() const { return m_pchData; }
  404. AFX_INLINE const WCHAR * CString::Get() const { return m_pchData; }
  405. AFX_INLINE const WCHAR * CString::GetNIE() const { return IsEmpty() ? NULL : m_pchData; }
  406. AFX_INLINE char * CString::GetAnsiNIE() const { return IsEmpty() ? NULL : GetAnsi(); }
  407. AFX_INLINE char * CString::ReleaseAnsi() const { char * lpsz = GetAnsi(); m_pchDataAnsi = NULL; return lpsz; }
  408. AFX_INLINE int CString::SafeStrlen(const WCHAR * lpsz) { if ( lpsz == NULL ) return 0; else { SIZE_T ilen = wcslen(lpsz); if ( ilen <= INT_MAX ) return (int) ilen; return 0; } }
  409. AFX_INLINE void CString::FreeData(CStringData<WCHAR>* pData) { delete [] ((BYTE *)pData); }
  410. AFX_INLINE int CString::Compare(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::Compare: Invalid string"); return wcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
  411. AFX_INLINE int CString::CompareNoCase(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return _wcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
  412. AFX_INLINE int CString::Collate(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::Collate: Invalid string"); return wcscoll(m_pchData, lpsz); } // locale sensitive
  413. AFX_INLINE int CString::CollateNoCase(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::CollateNoCase: Invalid string"); return _wcsicoll(m_pchData, lpsz); } // locale sensitive
  414. AFX_INLINE int CString::ComparePart(const WCHAR * lpsz, int start, int nChars) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return wcsncmp(m_pchData+start, lpsz, nChars); } // MBCS/Unicode aware
  415. AFX_INLINE int CString::ComparePartNoCase(const WCHAR * lpsz, int start, int nChars) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return _wcsnicmp(m_pchData+start, lpsz, nChars); } // MBCS/Unicode aware
  416. AFX_INLINE int CString::EndsWith(const WCHAR * lpsz) const
  417. {
  418. int ilen = SafeStrlen(lpsz);
  419. int start = GetLength() - ilen;
  420. if (start < 0)
  421. {
  422. start = 0;
  423. }
  424. return ComparePart(lpsz, start, ilen);
  425. }
  426. AFX_INLINE int CString::EndsWithNoCase(const WCHAR * lpsz) const
  427. {
  428. int ilen = SafeStrlen(lpsz);
  429. int start = GetLength() - ilen;
  430. if (start < 0)
  431. {
  432. start = 0;
  433. }
  434. return ComparePartNoCase(lpsz, start, ilen);
  435. }
  436. AFX_INLINE WCHAR CString::GetAt(int nIndex) const
  437. {
  438. ASSERT(nIndex >= 0, "CString::GetAt: negative index");
  439. ASSERT(nIndex < GetData()->nDataLength, "CString::GetData: index larger than string");
  440. return m_pchData[nIndex];
  441. }
  442. AFX_INLINE WCHAR CString::operator[](int nIndex) const
  443. {
  444. // same as GetAt
  445. ASSERT(nIndex >= 0, "CString::operator[]: negative index");
  446. ASSERT(nIndex < GetData()->nDataLength, "CString::GetData: index larger than string");
  447. return m_pchData[nIndex];
  448. }
  449. AFX_INLINE BOOL CString::IsPathSep(int index) const
  450. {
  451. return ShimLib::IsPathSep(GetAt(index));
  452. }
  453. #undef afxEmptyString
  454. // ************************************************************************************
  455. // Exception filter for CString __try/__except blocks
  456. // Return EXCEPTION_EXECUTE_HANDLER if this is a CString exception
  457. // otherwise return EXCEPTION_CONTINUE_SEARCH
  458. extern int CStringExceptionFilter(PEXCEPTION_POINTERS pexi);
  459. #if defined(USE_SEH)
  460. #define CSTRING_THROW_EXCEPTION RaiseException((DWORD)ShimLib::CString::eCStringNoMemoryException, 0, 1, &ShimLib::CString::m_CStringExceptionValue); // Continuable, CString specific memory exception
  461. #define CSTRING_TRY __try
  462. #define CSTRING_CATCH __except( ShimLib::CString::ExceptionFilter(GetExceptionInformation()) )
  463. #else
  464. // If we use the C++ exception handler, we need to make sure we have the /GX compile flag
  465. #define CSTRING_THROW_EXCEPTION throw ShimLib::CString::CStringError();
  466. #define CSTRING_TRY try
  467. #define CSTRING_CATCH catch( ShimLib::CString::CStringError & /* cse */ )
  468. #endif
  469. }; // end of namespace ShimLib
  470. // ************************************************************************************
  471. namespace ShimLib
  472. {
  473. /*++
  474. Read a registry value into this CString.
  475. REG_EXPAND_SZ is automatically expanded and the type is changed to REG_SZ
  476. If the type is not REG_SZ or REG_EXPAND_SZ, then csRegValue.GetLength()
  477. is the number of *bytes* in the string.
  478. This is typically used to only read REG_SZ/REG_EXPAND_SZ registry values.
  479. Note: This API may only be called after SHIM_STATIC_DLLS_INITIALIZED
  480. --*/
  481. LONG RegQueryValueExW(
  482. CString & csValue,
  483. HKEY hKeyRoot,
  484. const WCHAR * lpszKey,
  485. const WCHAR * lpszValue);
  486. /*++
  487. Get the ShSpecial folder name.
  488. Note: This API may only be called after SHIM_STATIC_DLLS_INITIALIZED
  489. --*/
  490. BOOL SHGetSpecialFolderPathW(
  491. CString & csFolder,
  492. int nFolder,
  493. HWND hwndOwner = NULL
  494. );
  495. // ************************************************************************************
  496. /*++
  497. A tokenizer--a replacement for strtok.
  498. Init the class with the string and token delimiter.
  499. Call GetToken to peel off the next token.
  500. ++*/
  501. class CStringToken
  502. {
  503. public:
  504. CStringToken(const CString & csToken, const CString & csDelimit);
  505. // Get the next token
  506. BOOL GetToken(CString & csNextToken);
  507. // Count the number of remaining tokens.
  508. int GetCount() const;
  509. protected:
  510. int m_nPos;
  511. CString m_csToken;
  512. CString m_csDelimit;
  513. BOOL GetToken(CString & csNextToken, int & nPos) const;
  514. };
  515. // ************************************************************************************
  516. /*++
  517. A simple class to assist in command line parsing
  518. --*/
  519. class CStringParser
  520. {
  521. public:
  522. CStringParser(const WCHAR * lpszCl, const WCHAR * lpszSeperators);
  523. ~CStringParser();
  524. int GetCount() const; // Return the current number of args
  525. CString & Get(int nIndex);
  526. CString & operator[](int nIndex);
  527. // Give ownership of the CString array to the caller
  528. // Caller must call delete [] cstring
  529. CString * ReleaseArgv();
  530. protected:
  531. int m_ncsArgList;
  532. CString * m_csArgList;
  533. void SplitSeperator(const CString & csCl, const CString & csSeperator);
  534. void SplitWhite(const CString & csCl);
  535. };
  536. inline int CStringParser::GetCount() const
  537. {
  538. return m_ncsArgList;
  539. }
  540. inline CString & CStringParser::Get(int nIndex)
  541. {
  542. return m_csArgList[nIndex];
  543. }
  544. inline CString & CStringParser::operator[](int nIndex)
  545. {
  546. return m_csArgList[nIndex];
  547. }
  548. inline CString * CStringParser::ReleaseArgv()
  549. {
  550. CString * argv = m_csArgList;
  551. m_csArgList = NULL;
  552. m_ncsArgList = 0;
  553. return argv;
  554. }
  555. }; // end of namespace ShimLib
  556. // ************************************************************************************