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.

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