Source code of Windows XP (NT5)
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.

821 lines
16 KiB

  1. //*****************************************************************************
  2. //
  3. // Support Class: CSTRING
  4. //
  5. // Purpose: Handle strings for the application. CSTRING does smart memory
  6. // management for strings.
  7. //
  8. // Notes: For more information, see CompatAdmin.DOC
  9. //
  10. // History
  11. //
  12. // A-COWEN Dec 12, 2000 Wrote it.
  13. //
  14. //*****************************************************************************
  15. #define MAX_STRING_SIZE 2048
  16. #ifndef UNICODE
  17. #define UNICODE
  18. #endif
  19. #ifndef _UNICODE
  20. #define _UNICODE
  21. #endif
  22. #include "stdarg.h"
  23. class CMemException {
  24. private:
  25. TCHAR m_szMessageHeading[100];
  26. TCHAR m_szMessage[512] ;
  27. public:
  28. CMemException()
  29. {
  30. _tcscpy(m_szMessageHeading,TEXT("Insufficient Memory Exception"));
  31. _tcscpy(m_szMessage, TEXT("Insufficient Memory Exception"));
  32. }
  33. void SetString(TCHAR* szMsg )
  34. {
  35. int nch = _sntprintf(m_szMessage,
  36. sizeof(m_szMessage)/sizeof(TCHAR),
  37. TEXT("%s : %s"), m_szMessageHeading, szMsg);
  38. #ifdef __DEBUG
  39. if (nch < 0) {
  40. MessageBox(NULL,TEXT("Please make the error message Short"),TEXT("Long Error Message"), MB_ICONWARNING);
  41. }
  42. #endif
  43. }
  44. TCHAR* GetString()
  45. {
  46. return m_szMessage;
  47. }
  48. };
  49. class CSTRING {
  50. public:
  51. WCHAR * pszString;
  52. LPSTR pszANSI;
  53. public:
  54. CSTRING()
  55. {
  56. Init();
  57. }
  58. CSTRING(CSTRING & Str)
  59. {
  60. Init();
  61. SetString(Str.pszString);
  62. }
  63. CSTRING(LPTSTR szString)
  64. {
  65. Init();
  66. SetString(szString);
  67. }
  68. CSTRING(UINT uID)
  69. {
  70. Init();
  71. SetString(uID);
  72. }
  73. ~CSTRING()
  74. {
  75. Release();
  76. }
  77. void Init()
  78. {
  79. pszString = NULL;
  80. pszANSI = NULL;
  81. }
  82. void Release(void)
  83. {
  84. if ( NULL != pszString )
  85. delete pszString;
  86. if ( NULL != pszANSI )
  87. delete pszANSI;
  88. pszString = NULL;
  89. pszANSI = NULL;
  90. }
  91. BOOL SetString(UINT uID)
  92. {
  93. TCHAR szString[MAX_STRING_SIZE];
  94. if ( 0 != LoadString(GetModuleHandle(NULL), uID, szString, MAX_STRING_SIZE) )
  95. return SetString(szString);
  96. return FALSE;
  97. }
  98. BOOL SetString(LPCTSTR szStringIn)
  99. {
  100. if ( pszString == szStringIn )
  101. return TRUE;
  102. Release();
  103. if ( NULL == szStringIn )
  104. return TRUE;
  105. UINT uLen = _tcslen(szStringIn) + 1;
  106. pszString = new TCHAR[uLen];
  107. if ( NULL != pszString )
  108. _tcscpy(pszString,szStringIn);
  109. else {
  110. CMemException memException;
  111. throw memException;
  112. return FALSE;
  113. }
  114. return TRUE;
  115. }
  116. operator LPCSTR()
  117. {
  118. if (pszANSI != NULL) delete pszANSI;
  119. int cbSize = WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,this->pszString, -1, NULL, 0, NULL, NULL);
  120. pszANSI = (LPSTR) new CHAR [cbSize+1];
  121. ZeroMemory(pszANSI,sizeof(pszANSI) );
  122. if (pszANSI == NULL) {
  123. MEM_ERR;
  124. return NULL;
  125. }
  126. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,this->pszString, -1, pszANSI, cbSize+1, NULL, NULL);
  127. return pszANSI;
  128. }
  129. operator LPWSTR()
  130. {
  131. return pszString;
  132. }
  133. operator LPCWSTR()
  134. {
  135. return pszString;
  136. }
  137. CSTRING& operator =(LPCWSTR szStringIn)
  138. {
  139. #ifndef UNICODE
  140. TCHAR szTemp[MAX_STRING_SIZE];
  141. int nLength = lstrlenW(szStringIn);
  142. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,szStringIn,nLength,szTemp,MAX_STRING_SIZE,NULL,NULL);
  143. szTemp[nLength] = 0;
  144. SetString(szTemp);
  145. #else
  146. SetString(szStringIn);
  147. #endif
  148. return *this;
  149. }
  150. CSTRING& operator =(CSTRING & szStringIn)
  151. {
  152. SetString(szStringIn.pszString);
  153. return *this;
  154. }
  155. BOOL operator == (CSTRING & szString)
  156. {
  157. if (NULL == pszString && NULL == szString.pszString) {
  158. return TRUE;
  159. }
  160. if ( NULL == pszString || NULL == szString.pszString)
  161. return FALSE;
  162. if ( 0 == lstrcmpi(szString.pszString,pszString) )
  163. return TRUE;
  164. return FALSE;
  165. }
  166. BOOL operator == (LPCTSTR szString)
  167. {
  168. if (NULL == pszString && NULL == szString) {
  169. return TRUE;
  170. }
  171. if ( NULL == pszString || NULL == szString)
  172. return FALSE;
  173. if ( 0 == lstrcmpi(szString,pszString) )
  174. return TRUE;
  175. return FALSE;
  176. }
  177. BOOL operator != (CSTRING & szString)
  178. {
  179. if (NULL == pszString && NULL == szString.pszString) {
  180. return FALSE;
  181. }
  182. if ( NULL == pszString || NULL == szString.pszString)
  183. return TRUE;
  184. if ( 0 == lstrcmpi(szString.pszString,pszString) )
  185. return FALSE;
  186. return TRUE;
  187. }
  188. BOOL operator != (LPCTSTR szString)
  189. {
  190. if ( NULL == pszString )
  191. return TRUE;
  192. if ( 0 == lstrcmpi(szString,pszString) )
  193. return FALSE;
  194. return TRUE;
  195. }
  196. BOOL operator <= (CSTRING &szString)
  197. {
  198. return ( (lstrcmpi (*this,szString) <= 0 ) ? TRUE : FALSE);
  199. }
  200. BOOL operator < (CSTRING &szString)
  201. {
  202. return ( (lstrcmpi (*this,szString) < 0 ) ? TRUE : FALSE);
  203. }
  204. BOOL operator >= (CSTRING &szString)
  205. {
  206. return ( (lstrcmpi (*this,szString) >= 0 ) ? TRUE : FALSE);
  207. }
  208. BOOL operator > (CSTRING &szString)
  209. {
  210. return ( (lstrcmpi (*this,szString) > 0 ) ? TRUE : FALSE);
  211. }
  212. void __cdecl sprintf(LPCTSTR szFormat, ...)
  213. {
  214. va_list list;
  215. TCHAR szTemp[MAX_STRING_SIZE];
  216. va_start(list,szFormat);
  217. int cch = _vsntprintf(szTemp, sizeof(szTemp)/sizeof(szTemp[0]), szFormat, list);
  218. #ifdef __DEBUG
  219. if (cch < 0) {
  220. DBGPRINT((sdlError,("CSTRING::sprintf"), ("%s"), TEXT("Too long for _vsntprintf()") ) );
  221. }
  222. #endif
  223. SetString(szTemp);
  224. }
  225. UINT Trim()
  226. {
  227. CSTRING szTemp = *this;
  228. UINT uOrig_length = Length();
  229. TCHAR *pStart = szTemp.pszString,
  230. *pEnd = szTemp.pszString + uOrig_length - 1;
  231. while ( *pStart== TEXT(' ') ) ++pStart;
  232. while ( (pEnd >= pStart) && ( *pEnd == TEXT(' ') ) ) --pEnd;
  233. *( pEnd + 1) = TEXT('\0');//Keep it safe
  234. UINT nLength = pEnd - pStart;
  235. ++nLength; // For the character
  236. //
  237. //If no trimming has been done, return right away
  238. //
  239. if ( uOrig_length == nLength ) {
  240. return nLength;
  241. }
  242. SetString(pStart);
  243. return ( nLength);
  244. }
  245. BOOL SetChar(int nPos, TCHAR chValue)
  246. {
  247. //Pos is 0 based
  248. int length = Length();
  249. if (nPos >= length || length <= 0 ) {
  250. return FALSE;
  251. }
  252. this->pszString[nPos] = chValue;
  253. return TRUE;
  254. }
  255. static Trim(IN OUT LPTSTR str)
  256. {
  257. UINT uOrig_length = lstrlen(str); // Original length
  258. TCHAR *pStart = str,
  259. *pEnd = str + uOrig_length - 1;
  260. while ( *pStart== TEXT(' ') ) ++pStart;
  261. while ( (pEnd >= pStart) && ( *pEnd == TEXT(' ') ) ) --pEnd;
  262. *( pEnd + 1) = TEXT('\0');//Keep it safe
  263. UINT nLength = pEnd - pStart;
  264. ++nLength; // For the character
  265. //
  266. //If no trimming has been done, return right away
  267. //
  268. if ( uOrig_length == nLength ) {
  269. return nLength;
  270. }
  271. wmemmove(str,pStart, (nLength+1) * sizeof(TCHAR) ); // +1 for the 0 character.
  272. return (nLength);
  273. }
  274. BOOL EndsWith(LPCTSTR szSuffix)
  275. {
  276. const TCHAR* pStr = this->pszString;
  277. const TCHAR* pPos = NULL;
  278. pPos = _tcsrchr(pStr,TEXT('.'));
  279. if (pPos != NULL )
  280. if (_tcsicmp(pPos,szSuffix) == 0 ) return TRUE;
  281. return FALSE;
  282. }
  283. PCTSTR strcat(CSTRING & szStr)
  284. {
  285. return strcat((LPCTSTR)szStr);
  286. }
  287. LPCTSTR strcat(LPCTSTR pString)
  288. {
  289. if (pString == NULL) {
  290. return pszString;
  291. }
  292. int nLengthCat = _tcslen(pString);
  293. int nLengthStr = Length();
  294. TCHAR *szTemp = new TCHAR [nLengthStr + nLengthCat + 1];
  295. if ( szTemp == NULL ) {
  296. CMemException memException;
  297. throw memException;
  298. return NULL;
  299. }
  300. szTemp[0] = 0;
  301. //
  302. // Copy only if pszString != NULL. Otherwise we will get mem exception/garbage value
  303. //
  304. if (nLengthStr ) _tcsncpy(szTemp, pszString, nLengthStr);
  305. _tcsncpy(szTemp+nLengthStr, pString, nLengthCat);
  306. szTemp[nLengthStr + nLengthCat] = TEXT('\0');
  307. Release();
  308. pszString = szTemp;
  309. return pszString;
  310. }//strcat
  311. BOOL isNULL()
  312. {
  313. return(this->pszString == NULL);
  314. }
  315. int Length(void)
  316. {
  317. if ( NULL == pszString )
  318. return 0;
  319. return lstrlen(pszString);
  320. }
  321. void GUID(GUID & Guid)
  322. {
  323. TCHAR szGUID[80];
  324. // NOTE: We could use StringFromGUID2, or StringfromIID, but that
  325. // would require loading OLE32.DLL. Unless we have to, avoid it.
  326. // OR you could use functions in SDBAPI
  327. _stprintf(szGUID, TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  328. Guid.Data1,
  329. Guid.Data2,
  330. Guid.Data3,
  331. Guid.Data4[0],
  332. Guid.Data4[1],
  333. Guid.Data4[2],
  334. Guid.Data4[3],
  335. Guid.Data4[4],
  336. Guid.Data4[5],
  337. Guid.Data4[6],
  338. Guid.Data4[7]);
  339. SetString(szGUID);
  340. }
  341. void ShortFilename(void)
  342. {
  343. TCHAR szTemp[MAX_PATH_BUFFSIZE];
  344. LPTSTR szHold;
  345. // BUGBUG consider using shlwapi PathFindFileName
  346. _tcscpy(szTemp,pszString);
  347. LPTSTR szWalk = szTemp;
  348. szHold = szWalk;
  349. while ( 0 != *szWalk ) {
  350. //
  351. // use _tcsrchr BUGBUG
  352. //
  353. if ( TEXT('\\') == *szWalk )
  354. szHold = szWalk+1;
  355. ++szWalk;
  356. }
  357. SetString(szHold);
  358. }
  359. BOOL RelativeFile(CSTRING & szPath)
  360. {
  361. return RelativeFile((LPCTSTR)szPath);
  362. }
  363. //
  364. // BUGBUG : consider using shlwapi PathRelativePathTo
  365. //
  366. BOOL RelativeFile(LPCTSTR pExeFile)
  367. {
  368. LPCTSTR pMatchFile = pszString;
  369. int nLenExe = 0;
  370. int nLenMatch = 0;
  371. LPCTSTR pExe = NULL;
  372. LPCTSTR pMatch = NULL;
  373. LPTSTR pReturn = NULL;
  374. TCHAR result[MAX_PATH_BUFFSIZE];
  375. LPTSTR resultIdx = result;
  376. BOOL bCommonBegin = FALSE; // Indicates if the paths have a common beginning
  377. *result = TEXT('\0');
  378. //
  379. // Ensure that the beginning of the path matches between the two files
  380. //
  381. // BUGBUG this code has to go -- look into replacing this with Shlwapi Path*
  382. //
  383. //
  384. pExe = _tcschr(pExeFile, TEXT('\\'));
  385. pMatch = _tcschr(pMatchFile, TEXT('\\'));
  386. while ( pExe && pMatch ) {
  387. nLenExe = pExe - pExeFile;
  388. nLenMatch = pMatch - pMatchFile;
  389. if ( nLenExe != nLenMatch ) {
  390. break;
  391. }
  392. if ( !(_tcsnicmp(pExeFile, pMatchFile, nLenExe) == 0) ) {
  393. break;
  394. }
  395. bCommonBegin = TRUE;
  396. pExeFile = pExe + 1;
  397. pMatchFile = pMatch + 1;
  398. pExe = _tcschr(pExeFile, TEXT('\\'));
  399. pMatch = _tcschr(pMatchFile, TEXT('\\'));
  400. }
  401. //
  402. // Walk the path and put '..\' where necessary
  403. //
  404. if ( bCommonBegin ) {
  405. while ( pExe ) {
  406. _tcscpy(resultIdx, TEXT("..\\"));
  407. resultIdx = resultIdx + 3;
  408. pExeFile = pExe + 1;
  409. pExe = _tcschr(pExeFile, TEXT('\\'));
  410. }
  411. _tcscpy(resultIdx, pMatchFile);
  412. SetString(result);
  413. }
  414. else{
  415. return FALSE;
  416. }
  417. return TRUE;
  418. }
  419. };
  420. //
  421. // BUGBUG: consider using list class from STL
  422. //
  423. //
  424. template <class T> class CList {
  425. protected:
  426. typedef struct _tagList {
  427. T Entry;
  428. struct _tagList * pNext;
  429. } LIST, *PLIST;
  430. PLIST m_pHead;
  431. PLIST m_pCurrent;
  432. PLIST m_pFindPrev;
  433. private:
  434. PLIST Find(T * pData)
  435. {
  436. PLIST pWalk = m_pHead;
  437. m_pFindPrev = NULL;
  438. while ( NULL != pWalk ) {
  439. if ( pData == &pWalk->Entry )
  440. return pWalk;
  441. m_pFindPrev = pWalk;
  442. pWalk = pWalk->pNext;
  443. }
  444. return NULL;
  445. }
  446. public:
  447. CList()
  448. {
  449. Init();
  450. }
  451. ~CList()
  452. {
  453. Release();
  454. }
  455. void Init(void)
  456. {
  457. m_pHead = NULL;
  458. m_pCurrent = NULL;
  459. }
  460. void Release(void)
  461. {
  462. while ( NULL != m_pHead ) {
  463. PLIST pHold = m_pHead->pNext;
  464. delete m_pHead;
  465. m_pHead = pHold;
  466. }
  467. }
  468. T * First(void)
  469. {
  470. m_pCurrent = m_pHead;
  471. if ( NULL == m_pHead )
  472. return NULL;
  473. return &m_pHead->Entry;
  474. }
  475. T * Next(void)
  476. {
  477. if ( NULL != m_pCurrent ) {
  478. m_pCurrent = m_pCurrent->pNext;
  479. if ( NULL != m_pCurrent )
  480. return &m_pCurrent->Entry;
  481. }
  482. return NULL;
  483. }
  484. BOOL Insert(T * pInsert, T * pAfter = NULL)
  485. {
  486. PLIST pNew = new LIST;
  487. if ( NULL == pNew )
  488. return FALSE;
  489. pNew->Entry = *pInsert;
  490. if ( NULL == pAfter ) {
  491. pNew->pNext = m_pHead;
  492. m_pHead = pNew;
  493. } else {
  494. PLIST pHold = Find(pAfter);
  495. if ( NULL == pHold ) {
  496. delete pNew;
  497. return FALSE;
  498. }
  499. pNew->pNext = pHold->pNext;
  500. pHold->pNext = pNew;
  501. }
  502. return TRUE;
  503. }
  504. T * Insert(T * pAfter = NULL)
  505. {
  506. PLIST pNew = new LIST;
  507. if ( NULL == pNew )
  508. return NULL;
  509. if ( NULL == pAfter ) {
  510. pNew->pNext = m_pHead;
  511. m_pHead = pNew;
  512. } else {
  513. PLIST pHold = Find(pAfter);
  514. if ( NULL == pHold ) {
  515. delete pNew;
  516. return NULL;
  517. }
  518. pNew->pNext = pHold->pNext;
  519. pHold->pNext = pNew;
  520. }
  521. return &pNew->Entry;
  522. }
  523. BOOL Delete(T * pEntry)
  524. {
  525. PLIST pHold = Find(pEntry);
  526. if ( NULL == pHold )
  527. return FALSE;
  528. if ( NULL != m_pFindPrev ) {
  529. m_pFindPrev->pNext = pHold->pNext;
  530. delete pHold;
  531. } else {
  532. m_pHead = m_pHead->pNext;
  533. delete m_pHead;
  534. }
  535. m_pCurrent = NULL;
  536. return TRUE;
  537. }
  538. };
  539. typedef struct _tagSList {
  540. CSTRING szStr;
  541. union {
  542. PVOID pExtraData;
  543. UINT uExtraData;
  544. DWORD dwExtraData;
  545. int nExtraData;
  546. };
  547. struct _tagSList * pNext;
  548. } STRLIST, *PSTRLIST;
  549. class CSTRINGList {
  550. public:
  551. PSTRLIST m_pHead;
  552. PSTRLIST m_pTail;
  553. public:
  554. CSTRINGList()
  555. {
  556. m_pHead = NULL;
  557. m_pTail = NULL;
  558. }
  559. ~CSTRINGList()
  560. {
  561. while ( NULL != m_pHead ) {
  562. PSTRLIST pHold = m_pHead->pNext;
  563. delete m_pHead;
  564. m_pHead = pHold;
  565. }
  566. }
  567. BOOL AddString(CSTRING & Str, PVOID pExtraData = NULL)
  568. {
  569. return AddString((LPCTSTR)Str,pExtraData);
  570. }
  571. BOOL AddString(LPCTSTR pStr, PVOID pExtraData = NULL)
  572. {
  573. PSTRLIST pNew = new STRLIST;
  574. if ( NULL == pNew )
  575. return FALSE;
  576. pNew->szStr = pStr;
  577. pNew->pExtraData = pExtraData;
  578. pNew->pNext = NULL;
  579. if ( NULL == m_pTail ) {
  580. m_pHead = m_pTail = pNew;
  581. } else {
  582. m_pTail->pNext = pNew;
  583. m_pTail = pNew;
  584. }
  585. return TRUE;
  586. }
  587. };