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.

561 lines
12 KiB

  1. /******************************************************************************
  2. Source File: String.CPP
  3. String Handling class implementation, v 98.6 1/2
  4. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved.
  5. Change History:
  6. 01-08-97 Bob Kjelgaard
  7. 01-03-97 Bob Kjelgaard Added special functions to aid port extraction
  8. for plug-and-play.
  9. 07-05-97 Tim Wells Ported to NT.
  10. ******************************************************************************/
  11. //
  12. // Precompiled header
  13. //
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // Include
  18. //
  19. #include "sti_ci.h"
  20. //
  21. // Extern
  22. //
  23. extern HINSTANCE g_hDllInstance;
  24. //
  25. // Function
  26. //
  27. CString::CString(const CString& csRef) {
  28. m_lpstr = (csRef.m_lpstr && *csRef.m_lpstr) ?
  29. new TCHAR[1 + lstrlen(csRef.m_lpstr)] : NULL;
  30. if (m_lpstr)
  31. lstrcpy(m_lpstr, csRef.m_lpstr);
  32. }
  33. CString::CString(LPCTSTR lpstrRef){
  34. DWORD dwLength;
  35. _try {
  36. dwLength = lstrlen(lpstrRef);
  37. } // _try {
  38. _except(EXCEPTION_EXECUTE_HANDLER) {
  39. dwLength = 0;
  40. } // _except(EXCEPTION_EXECUTE_HANDLER)
  41. if( (NULL != lpstrRef)
  42. && (NULL != *lpstrRef)
  43. && (0 != dwLength) )
  44. {
  45. m_lpstr = new TCHAR[dwLength+1];
  46. lstrcpy(m_lpstr, lpstrRef);
  47. }
  48. } // CString::CString(LPCTSTR lpstrRef)
  49. const CString& CString::operator =(const CString& csRef) {
  50. Empty();
  51. m_lpstr = (csRef.m_lpstr && *csRef.m_lpstr) ?
  52. new TCHAR[1 + lstrlen(csRef.m_lpstr)] : NULL;
  53. if (m_lpstr)
  54. lstrcpy(m_lpstr, csRef.m_lpstr);
  55. return *this;
  56. }
  57. const
  58. CString&
  59. CString::operator =(
  60. LPCTSTR lpstrRef
  61. )
  62. {
  63. DWORD dwLength;
  64. Empty();
  65. _try {
  66. dwLength = lstrlen(lpstrRef);
  67. } // _try {
  68. _except(EXCEPTION_EXECUTE_HANDLER) {
  69. dwLength = 0;
  70. } // _except(EXCEPTION_EXECUTE_HANDLER)
  71. if( (NULL != lpstrRef)
  72. && (NULL != *lpstrRef)
  73. && (0 != dwLength) )
  74. {
  75. m_lpstr = new TCHAR[dwLength+1];
  76. lstrcpy(m_lpstr, lpstrRef);
  77. }
  78. return *this;
  79. } // CString::operator =(LPCTSTR lpstrRef)
  80. void CString::GetContents(HWND hwnd) {
  81. Empty();
  82. if (!IsWindow(hwnd))
  83. return;
  84. unsigned u = (unsigned) SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
  85. if (!u)
  86. return;
  87. m_lpstr = new TCHAR[++u];
  88. if(NULL != m_lpstr){
  89. SendMessage(hwnd, WM_GETTEXT, u, (LPARAM) m_lpstr);
  90. }
  91. }
  92. void CString::FromTable(unsigned uid) {
  93. TCHAR acTemp[MAX_PATH+1];
  94. memset(acTemp, 0, sizeof(acTemp));
  95. LoadString(g_hDllInstance, uid, acTemp, ARRAYSIZE(acTemp)-1);
  96. *this = acTemp;
  97. }
  98. void CString::Load(ATOM at, BOOL bGlobal) {
  99. TCHAR acTemp[MAX_PATH+1];
  100. memset(acTemp, 0, sizeof(acTemp));
  101. if(bGlobal){
  102. GlobalGetAtomName(at,
  103. acTemp,
  104. ARRAYSIZE(acTemp)-1);
  105. } else {
  106. GetAtomName(at,
  107. acTemp,
  108. sizeof(acTemp)/sizeof(TCHAR));
  109. }
  110. *this = acTemp;
  111. }
  112. void
  113. CString::Load(
  114. HINF hInf,
  115. LPCTSTR lpstrSection,
  116. LPCTSTR lpstrKeyword,
  117. DWORD dwFieldIndex,
  118. LPCTSTR lpstrDefault
  119. )
  120. {
  121. INFCONTEXT InfContext;
  122. TCHAR szKeyBuffer[MAX_PATH+1];
  123. TCHAR szValueBuffer[MAX_PATH+1];
  124. //
  125. // Initialize local.
  126. //
  127. memset(&InfContext, 0, sizeof(InfContext));
  128. memset(szKeyBuffer, 0, sizeof(szKeyBuffer));
  129. memset(szValueBuffer, 0, sizeof(szValueBuffer));
  130. //
  131. // Cleanup contents;
  132. //
  133. Empty();
  134. //
  135. // Check all parameters.
  136. //
  137. if( (NULL == lpstrSection)
  138. || (NULL == lpstrKeyword)
  139. || (!IS_VALID_HANDLE(hInf)) )
  140. {
  141. //
  142. // Invalid parameter.
  143. //
  144. goto Load_return;
  145. }
  146. //
  147. // Get matching line.
  148. //
  149. while(SetupFindFirstLine(hInf, lpstrSection, lpstrKeyword, &InfContext)){
  150. //
  151. // Get a field of a line.
  152. //
  153. if(SetupGetStringField(&InfContext, dwFieldIndex, szValueBuffer, ARRAYSIZE(szValueBuffer)-1, NULL)){
  154. *this = szValueBuffer;
  155. break;
  156. }// if(SetupGetStringField(&InfContext, dwFieldIndex, szValueBuffer, ARRAYSIZE(szValueBuffer)-1))
  157. } // while(SetupFindFirstLine(hInf, lpstrSection, lpstrKeyword, &InfContext))
  158. Load_return:
  159. return;
  160. } // CString::Load() Load from INF
  161. void CString::Load(HKEY hk, LPCTSTR lpstrKeyword) {
  162. TCHAR abTemp[MAX_PATH+1];
  163. ULONG lcbNeeded = sizeof(abTemp)-sizeof(TCHAR);
  164. memset(abTemp, 0, sizeof(abTemp));
  165. RegQueryValueEx(hk, lpstrKeyword, NULL, NULL, (PBYTE)abTemp, &lcbNeeded);
  166. *this = (LPCTSTR) abTemp;
  167. }
  168. void CString::MakeSystemPath(LPCTSTR lpstrFileName) {
  169. DWORD dwLength;
  170. if (m_lpstr)
  171. delete m_lpstr;
  172. _try {
  173. dwLength = lstrlen(lpstrFileName);
  174. } // _try {
  175. _except(EXCEPTION_EXECUTE_HANDLER) {
  176. dwLength = 0;
  177. } // _except(EXCEPTION_EXECUTE_HANDLER)
  178. m_lpstr = new TCHAR[MAX_PATH * 2];
  179. if( (NULL != m_lpstr)
  180. && (0 != dwLength)
  181. && (MAX_PATH >= dwLength) )
  182. {
  183. memset(m_lpstr, 0, MAX_PATH*2*sizeof(TCHAR));
  184. UINT uiLength = GetSystemDirectory (m_lpstr, MAX_PATH);
  185. if ( *(m_lpstr + uiLength) != TEXT('\\'))
  186. lstrcat (m_lpstr, TEXT("\\"));
  187. lstrcat (m_lpstr, lpstrFileName);
  188. }
  189. }
  190. void CString::Store(HKEY hk, LPCTSTR lpstrKey, LPCTSTR lpstrType) {
  191. DWORD dwLength;
  192. if (IsEmpty())
  193. return;
  194. _try {
  195. dwLength = lstrlen(lpstrKey);
  196. } // _try {
  197. _except(EXCEPTION_EXECUTE_HANDLER) {
  198. return;
  199. } // _except(EXCEPTION_EXECUTE_HANDLER)
  200. if (lpstrType && *lpstrType == TEXT('1')) {
  201. DWORD dwValue = Decode();
  202. RegSetValueEx(hk, lpstrKey, NULL, REG_DWORD, (LPBYTE) &dwValue,
  203. sizeof (DWORD));
  204. } else {
  205. RegSetValueEx(hk, lpstrKey, NULL, REG_SZ, (LPBYTE) m_lpstr,
  206. (1 + lstrlen(m_lpstr)) * sizeof(TCHAR) );
  207. }
  208. }
  209. // This one is a bit lame, but it does the job.
  210. DWORD CString::Decode() {
  211. if (IsEmpty())
  212. return 0;
  213. for (LPTSTR lpstrThis = m_lpstr;
  214. *lpstrThis && *lpstrThis == TEXT(' ');
  215. lpstrThis++)
  216. ;
  217. if (!*lpstrThis)
  218. return 0;
  219. // BIUGBUG
  220. if (lpstrThis[0] == TEXT('0') && (lpstrThis[1] | TEXT('\x20') ) == TEXT('x')) {
  221. // Hex string
  222. lpstrThis += 2;
  223. DWORD dwReturn = 0;
  224. while (*lpstrThis) {
  225. switch (*lpstrThis) {
  226. case TEXT('0'):
  227. case TEXT('1'):
  228. case TEXT('2'):
  229. case TEXT('3'):
  230. case TEXT('4'):
  231. case TEXT('5'):
  232. case TEXT('6'):
  233. case TEXT('7'):
  234. case TEXT('8'):
  235. case TEXT('9'):
  236. dwReturn <<= 4;
  237. dwReturn += ((*lpstrThis) - TEXT('0'));
  238. break;
  239. case TEXT('a'):
  240. case TEXT('A'):
  241. case TEXT('b'):
  242. case TEXT('c'):
  243. case TEXT('d'):
  244. case TEXT('e'):
  245. case TEXT('f'):
  246. case TEXT('B'):
  247. case TEXT('C'):
  248. case TEXT('D'):
  249. case TEXT('E'):
  250. case TEXT('F'):
  251. dwReturn <<= 4;
  252. dwReturn += 10 + ((*lpstrThis | TEXT('\x20')) - TEXT('a'));
  253. break;
  254. default:
  255. return dwReturn;
  256. }
  257. lpstrThis++;
  258. }
  259. return dwReturn;
  260. }
  261. for (DWORD dwReturn = 0;
  262. *lpstrThis && *lpstrThis >= TEXT('0') && *lpstrThis <= TEXT('9');
  263. lpstrThis++) {
  264. dwReturn *= 10;
  265. dwReturn += *lpstrThis - TEXT('0');
  266. }
  267. return dwReturn;
  268. }
  269. CString operator + (const CString& cs1, const CString& cs2) {
  270. if (cs1.IsEmpty())
  271. return cs2;
  272. if (cs2.IsEmpty())
  273. return cs1;
  274. CString csReturn;
  275. csReturn.m_lpstr = new TCHAR[ 1 + lstrlen(cs1) +lstrlen(cs2)];
  276. if(NULL != csReturn.m_lpstr){
  277. lstrcat(lstrcpy(csReturn.m_lpstr, cs1.m_lpstr), cs2.m_lpstr);
  278. }
  279. return csReturn;
  280. }
  281. CString operator + (const CString& cs1, LPCTSTR lpstr2) {
  282. DWORD dwLength;
  283. _try {
  284. dwLength = lstrlen(lpstr2);
  285. } // _try {
  286. _except(EXCEPTION_EXECUTE_HANDLER) {
  287. dwLength = 0;
  288. } // _except(EXCEPTION_EXECUTE_HANDLER)
  289. if(0 == dwLength)
  290. return cs1;
  291. if(cs1.IsEmpty())
  292. return lpstr2;
  293. CString csReturn;
  294. csReturn.m_lpstr = new TCHAR[ 1 + lstrlen(cs1) + dwLength];
  295. if(NULL != csReturn.m_lpstr){
  296. lstrcat(lstrcpy(csReturn.m_lpstr, cs1.m_lpstr), lpstr2);
  297. }
  298. return csReturn;
  299. }
  300. CString operator + (LPCTSTR lpstr1,const CString& cs2) {
  301. DWORD dwLength;
  302. _try {
  303. dwLength = lstrlen(lpstr1);
  304. } // _try {
  305. _except(EXCEPTION_EXECUTE_HANDLER) {
  306. dwLength = 0;
  307. } // _except(EXCEPTION_EXECUTE_HANDLER)
  308. if(0 == dwLength)
  309. return cs2;
  310. if (cs2.IsEmpty())
  311. return lpstr1;
  312. CString csReturn;
  313. csReturn.m_lpstr = new TCHAR[ 1 + dwLength +lstrlen(cs2)];
  314. if(NULL != csReturn.m_lpstr){
  315. lstrcat(lstrcpy(csReturn.m_lpstr, lpstr1), cs2.m_lpstr);
  316. }
  317. return csReturn;
  318. }
  319. // CStringArray class- the implementation is a bit lame, but it isn't
  320. // really necessary to not be lame, at this point...
  321. CStringArray::CStringArray(unsigned uGrowBy) {
  322. m_ucItems = m_ucMax = 0;
  323. m_pcsContents = NULL;
  324. m_uGrowBy = uGrowBy ? uGrowBy : 10;
  325. }
  326. CStringArray::~CStringArray() {
  327. if (m_pcsContents)
  328. delete[] m_pcsContents;
  329. }
  330. VOID
  331. CStringArray::Cleanup() {
  332. if (m_pcsContents){
  333. delete[] m_pcsContents;
  334. }
  335. m_pcsContents = NULL;
  336. m_ucItems = m_ucMax = 0;
  337. }
  338. void CStringArray::Add(LPCTSTR lpstr) {
  339. if (m_ucItems >= m_ucMax) {
  340. CString *pcsNew = new CString[m_ucMax += m_uGrowBy];
  341. if (!pcsNew) {
  342. m_ucMax -= m_uGrowBy;
  343. return;
  344. }
  345. for (unsigned u = 0; u < m_ucItems; u++)
  346. pcsNew[u] = m_pcsContents[u];
  347. delete[] m_pcsContents;
  348. m_pcsContents = pcsNew;
  349. }
  350. m_pcsContents[m_ucItems++] = lpstr;
  351. }
  352. CString& CStringArray::operator [](unsigned u) {
  353. return (u < m_ucItems) ? m_pcsContents[u] : m_csEmpty;
  354. }
  355. // Split a string into tokens, and make an array of it
  356. void CStringArray::Tokenize(LPTSTR lpstr, TCHAR cSeparator) {
  357. BOOL fInsideQuotes = FALSE;
  358. TCHAR cPreviousChar = TEXT('\0');
  359. if (m_pcsContents) {
  360. delete[] m_pcsContents;
  361. m_pcsContents = NULL;
  362. m_ucItems = m_ucMax = 0;
  363. }
  364. if (!lpstr)
  365. return;
  366. for (LPTSTR lpstrThis = lpstr; *lpstr; lpstr = lpstrThis) {
  367. /*
  368. for (; *lpstrThis && *lpstrThis != cSeparator; lpstrThis++) {
  369. }
  370. */
  371. //
  372. // Skip for next separator , counting quotes
  373. //
  374. cPreviousChar = '\0';
  375. for (;*lpstrThis; lpstrThis++) {
  376. if (fInsideQuotes) {
  377. if (*lpstrThis == TEXT('"')) {
  378. if (cPreviousChar != TEXT('"')) {
  379. // Previous was not a quote - going out of quotation
  380. fInsideQuotes = FALSE;
  381. }
  382. else {
  383. // Previous char was tab too - continue BUGBUG should coalesce
  384. }
  385. cPreviousChar = TEXT('\0');
  386. }
  387. else {
  388. cPreviousChar = *lpstrThis;
  389. }
  390. continue;
  391. }
  392. else {
  393. if (*lpstrThis == TEXT('"')) {
  394. // Starting quote
  395. fInsideQuotes = TRUE;
  396. cPreviousChar = TEXT('\0');
  397. continue;
  398. }
  399. if (*lpstrThis == cSeparator) {
  400. // Got to separator outside of quote - break the loop
  401. break;
  402. }
  403. }
  404. }
  405. if (*lpstrThis) {
  406. *lpstrThis = '\0';
  407. Add(lpstr);
  408. *lpstrThis++ = cSeparator;
  409. }
  410. else
  411. Add(lpstr);
  412. }
  413. }