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.

518 lines
13 KiB

  1. #include "stdafx.h"
  2. #include "utils.h"
  3. #include "globals.h"
  4. #include "trapreg.h"
  5. //***************************************************************************
  6. //
  7. // MapEventToSeverity
  8. //
  9. // Extract the severity field from the event ID and convert it to a
  10. // string equivallent.
  11. //
  12. // Parameters:
  13. // DWORD dwEvent
  14. // The full event ID
  15. //
  16. // CString& sResult
  17. // The severity code string is returned here.
  18. //
  19. // Returns:
  20. // The severity code string is returned via sResult.
  21. //
  22. // Status:
  23. //
  24. //***************************************************************************
  25. void MapEventToSeverity(DWORD dwEvent, CString& sResult)
  26. {
  27. //
  28. // Values are 32 bit event ID values layed out as follows:
  29. //
  30. // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  31. // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  32. // +---+-+-+-----------------------+-------------------------------+
  33. // |Sev|C|R| Facility | Code |
  34. // +---+-+-+-----------------------+-------------------------------+
  35. //
  36. // where
  37. //
  38. // Sev - is the severity code
  39. //
  40. // 00 - Success
  41. // 01 - Informational
  42. // 10 - Warning
  43. // 11 - Error
  44. //
  45. // C - is the Customer code flag
  46. //
  47. // R - is a reserved bit
  48. //
  49. // Facility - is the facility code
  50. //
  51. // Code - is the facility's status code
  52. //
  53. //
  54. // Define the facility codes
  55. static UINT auiResource[4] =
  56. {IDS_EVENT_SEV_SUCCESS,
  57. IDS_EVENT_SEV_INFORMATIONAL,
  58. IDS_EVENT_SEV_WARNING,
  59. IDS_EVENT_SEV_ERROR
  60. };
  61. int iSeverity = (dwEvent >> 30) & 3;
  62. sResult.LoadString(auiResource[iSeverity]);
  63. }
  64. //********************************************************************************
  65. // FindSubstring
  66. //
  67. // Find a substring in some text and return an index to the starting
  68. // position of the string if it is found.
  69. //
  70. // Parameters:
  71. // LPCSTR pszTemplate
  72. // Pointer to the string to find.
  73. //
  74. // LPCSTR pszText
  75. // Pointer to the text that will be searched
  76. // for the template string.
  77. //
  78. // Returns:
  79. // An index to the location of the substring within the text if it
  80. // is found, otherwise -1.
  81. //
  82. //********************************************************************************
  83. LONG FindSubstring(LPCTSTR pszTemplate, LPCTSTR pszText)
  84. {
  85. if (*pszTemplate == 0) {
  86. // An empty template string matches anything, so return zero.
  87. // This should never really happen since it doesn't make much
  88. // sense to search for nothing.
  89. return 0;
  90. }
  91. LPCTSTR pszTextStart = pszText;
  92. while (*pszText) {
  93. // Iterate through the character positions in the text
  94. // and return the index to the starting char in the string
  95. // if it is found.
  96. LPCTSTR pch1 = pszTemplate;
  97. LPCTSTR pch2 = pszText;
  98. while (*pch1 && (*pch1 == *pch2))
  99. {
  100. ++pch1;
  101. ++pch2;
  102. }
  103. if (*pch1 == 0) {
  104. // We reached the end of the template string, so there
  105. // must have been a match.
  106. return (LONG)(pszText - pszTextStart);
  107. }
  108. ++pszText;
  109. }
  110. // Failed to find the substring
  111. return -1;
  112. }
  113. //********************************************************************************
  114. // FindWholeWord
  115. //
  116. // Find a whole word in some text and return an index to the starting
  117. // position of the whole word if it is found. Whole word means the
  118. // specified template string followed by a whitespace or end of string.
  119. //
  120. // Parameters:
  121. // LPCSTR pszTemplate
  122. // Pointer to the "whole word" string to find.
  123. //
  124. // LPCSTR pszText
  125. // Pointer to the text that will be searched
  126. // for the template string.
  127. //
  128. // Returns:
  129. // An index to the location of the "whole word" substring within the text if it
  130. // is found, otherwise -1.
  131. //
  132. //********************************************************************************
  133. LONG FindWholeWord(LPCTSTR pszTemplate, LPCTSTR pszText)
  134. {
  135. if (*pszTemplate == 0) {
  136. // An empty search string matches anything, so return the index
  137. // of the first character.
  138. return 0;
  139. }
  140. // Iterate through each character position checking for a whole-word
  141. // match at each position.
  142. LONG nchTemplate = _tcslen(pszTemplate);
  143. LPCTSTR pszTextStart = pszText;
  144. LPCTSTR pchTextLimit = pszText + (_tcslen(pszText) - nchTemplate);
  145. while (pszText <= pchTextLimit) {
  146. // Check to see if the word is contained anywhere within the text
  147. INT iPos = FindSubstring(pszTemplate, pszText);
  148. if (iPos == -1) {
  149. return -1;
  150. }
  151. // Point at the location of the template string within the text
  152. pszText += iPos;
  153. // Get the prefix character
  154. INT ichPrefix;
  155. if (pszText == pszTextStart) {
  156. // Beginning of line counts as white space.
  157. ichPrefix = _T(' ');
  158. }
  159. else {
  160. ichPrefix = *(pszText - 1);
  161. }
  162. // Get the suffix character.
  163. INT ichSuffix = pszText[nchTemplate];
  164. if (ichSuffix == 0) {
  165. // End of line counts as whitespace
  166. ichSuffix = _T(' ');
  167. }
  168. // To match a whole word, the word must be bounded on either side
  169. // by whitespace.
  170. if (isspace(ichPrefix) && isspace(ichSuffix)) {
  171. return (LONG)(pszText - pszTextStart);
  172. }
  173. // Bump the text pointer to the next position so we don't do the
  174. // same thing all over again.
  175. ++pszText;
  176. }
  177. return -1;
  178. }
  179. void DecString(CString& sValue, int iValue)
  180. {
  181. // 32 bytes should be enough to hold any value
  182. TCHAR szValue[32];
  183. _itot(iValue, szValue, 10);
  184. sValue = szValue;
  185. }
  186. void DecString(CString& sValue, long lValue)
  187. {
  188. // 32 bytes should be enough to hold any value
  189. TCHAR szValue[32];
  190. _ltot(lValue, szValue, 10);
  191. sValue = szValue;
  192. }
  193. void DecString(CString& sValue, DWORD dwValue)
  194. {
  195. TCHAR szValue[32];
  196. _ultot(dwValue, szValue, 10);
  197. sValue = szValue;
  198. }
  199. CList::CList()
  200. {
  201. m_pndPrev = this;
  202. m_pndNext = this;
  203. }
  204. void CList::Link(CList*& pndHead)
  205. {
  206. if (pndHead == NULL)
  207. pndHead = this;
  208. else
  209. {
  210. m_pndNext = pndHead;
  211. m_pndPrev = pndHead->m_pndPrev;
  212. m_pndPrev->m_pndNext = this;
  213. m_pndNext->m_pndPrev = this;
  214. }
  215. }
  216. void CList::Unlink(CList*& pndHead)
  217. {
  218. if (pndHead == this)
  219. {
  220. if (m_pndNext == this)
  221. pndHead = NULL;
  222. else
  223. pndHead = m_pndNext;
  224. }
  225. m_pndPrev->m_pndNext = m_pndNext;
  226. m_pndNext->m_pndPrev = m_pndPrev;
  227. }
  228. //***************************************************************
  229. // GetFormattedValue
  230. //
  231. // Convert a value to ASCII and insert thousand separator characters
  232. // into resulting value string.
  233. //
  234. // Parameters:
  235. // CString& sValueDst
  236. // The place to return the converted value.
  237. //
  238. // LONG lValue
  239. // The value to convert.
  240. //
  241. //*****************************************************************
  242. void GetFormattedValue(CString& sValueDst, LONG lValue)
  243. {
  244. CString sValueSrc;
  245. DecString(sValueSrc, lValue);
  246. LONG nch = sValueSrc.GetLength();
  247. LPCTSTR pszSrc = sValueSrc;
  248. // Get a buffer as large as the source string plus the largest number of commas
  249. // plus one for the sign, one for the null terminator plus one character for slop.
  250. LPTSTR pszDst = sValueDst.GetBuffer(nch + nch / 3 + 3);
  251. // Copy any leading sign character.
  252. if ((*pszSrc == _T('+')) || (*pszSrc == _T('-'))) {
  253. *pszDst++ = *pszSrc++;
  254. --nch;
  255. }
  256. // Now copy the rest of the number and insert thousand separator characters in
  257. // the appropriate positions.
  258. LONG nchInitial = nch;
  259. while (nch > 0) {
  260. if ((nch % 3) == 0) {
  261. if (nch != nchInitial) {
  262. *pszDst++ = g_chThousandSep;
  263. }
  264. }
  265. *pszDst++ = *pszSrc++;
  266. --nch;
  267. }
  268. *pszDst = _T('\0');
  269. sValueDst.ReleaseBuffer();
  270. }
  271. //**************************************************************
  272. // GenerateRangeMessage
  273. //
  274. // Generate a message indicating that the user should enter a value
  275. // between some numbers nMin and nMax.
  276. //
  277. // Parameters:
  278. // CString& sMessage
  279. // The place to return the message.
  280. //
  281. // LONG nMin
  282. // The minimum valid value in the range.
  283. //
  284. // LONG nMax
  285. // The maximum valid value in the range.
  286. //
  287. //****************************************************************
  288. void GenerateRangeMessage(CString& sMessage, LONG nMin, LONG nMax)
  289. {
  290. CString sText;
  291. sMessage.LoadString(IDS_RANGE_MESSAGE_PREFIX);
  292. sMessage += _T(' ');
  293. GetFormattedValue(sText, nMin);
  294. sMessage += sText;
  295. sMessage += _T(' ');
  296. sText.LoadString(IDS_RANGE_VALUE_SEPARATOR);
  297. sMessage += sText;
  298. sMessage += _T(' ');
  299. GetFormattedValue(sText, nMax);
  300. sMessage += sText;
  301. sText.LoadString(IDS_SENTENCE_TERMINATOR);
  302. sMessage += sText;
  303. }
  304. //***************************************************************************
  305. // GetThousandSeparator
  306. //
  307. // Get the thousand separator character for the current locale.
  308. //
  309. // Parameters:
  310. // TCHAR* pchThousandSep
  311. // Pointer to the place to return the thousand separator character.
  312. //
  313. // Returns:
  314. // SCODE
  315. // S_OK if the thousand separator was returned.
  316. // E_FAIL if the thousand separator was not returned.
  317. //
  318. //**************************************************************************
  319. SCODE GetThousandSeparator(TCHAR* pchThousandSep)
  320. {
  321. // Digit + separator + 3 digits + decimal + two digits + null terminator + 4 slop
  322. #define MAX_CHARS_THOUSAND 12
  323. CString sValue;
  324. LPTSTR pszValue = sValue.GetBuffer(MAX_CHARS_THOUSAND);
  325. GetNumberFormat(NULL, 0, _T("1000"), NULL, pszValue, MAX_CHARS_THOUSAND);
  326. sValue.ReleaseBuffer();
  327. TCHAR ch = sValue[1];
  328. if (isdigit(ch)) {
  329. return E_FAIL;
  330. }
  331. *pchThousandSep = ch;
  332. return S_OK;
  333. }
  334. //***********************************************************************
  335. // IsDecimalInteger
  336. //
  337. // This function tests a string to see whether or not it contains a
  338. // valid integer expression.
  339. //
  340. // Parameters:
  341. // LPCTSTR pszValue
  342. // Pointer to the string to test.
  343. //
  344. // Returns:
  345. // BOOL
  346. // TRUE = The string contained a valid integer expression.
  347. // FALSE = The string did not contain a valid integer expression.
  348. //
  349. //***********************************************************************
  350. BOOL IsDecimalInteger(LPCTSTR pszValue)
  351. {
  352. // Accept leading white space
  353. while (iswspace(*pszValue)) {
  354. ++pszValue;
  355. }
  356. // Accept a leading plus or minus sign
  357. if ((*pszValue == _T('+')) || (*pszValue == _T('-'))) {
  358. ++pszValue;
  359. }
  360. // Skip a string of consecutive digits with embedded thousand separators
  361. BOOL bSawThousandSep = FALSE;
  362. LONG nDigits = 0;
  363. while (TRUE) {
  364. if (*pszValue == g_chThousandSep) {
  365. if (nDigits > 3) {
  366. return FALSE;
  367. }
  368. bSawThousandSep = TRUE;
  369. nDigits = 0;
  370. }
  371. else if (isdigit(*pszValue)) {
  372. ++nDigits;
  373. }
  374. else {
  375. break;
  376. }
  377. ++pszValue;
  378. }
  379. if (bSawThousandSep && nDigits != 3) {
  380. // If a thousand separater was encountered, then there must be
  381. // three digits to the right of the last thousand separator.
  382. return FALSE;
  383. }
  384. // Accept trailing whitespace
  385. if (iswspace(*pszValue)) {
  386. ++pszValue;
  387. }
  388. if (*pszValue == _T('\0')) {
  389. // We reached the end of the string, so it must have been a decimal integer.
  390. return TRUE;
  391. }
  392. else {
  393. // We did not rech the end of the string, so it couldn't have been a valid
  394. // decimal integer value.
  395. return FALSE;
  396. }
  397. }
  398. //***************************************************************************
  399. // AsciiToLong
  400. //
  401. // This function first validates a string to make sure that it is a properly
  402. // formatted integer expression, and then converts it to a long. Any embedded
  403. // characters, such as the thousand separator, are stripped out before the
  404. // conversion is done.
  405. //
  406. //
  407. // Parameters:
  408. // LPCTSTR pszValue
  409. // Pointer to the string value to convert.
  410. //
  411. // LONG* plResult
  412. // Pointer to the place to store the result.
  413. //
  414. // Returns:
  415. // SCODE
  416. // S_OK = The string contained a valid integer and the converted
  417. // value was returned via plResult.
  418. // E_FAIL = The string did not contain a properly formatted integer
  419. // expression.
  420. //
  421. //
  422. //**************************************************************************
  423. SCODE AsciiToLong(LPCTSTR pszValue, LONG* plResult)
  424. {
  425. if (!IsDecimalInteger(pszValue)) {
  426. return E_FAIL;
  427. }
  428. // Strip out any superfluous characters, such as the thousand separator
  429. // before converting from ascii to long.
  430. CString sStrippedValue;
  431. LPTSTR pszDst = sStrippedValue.GetBuffer(_tcslen(pszValue) + 1);
  432. TCHAR ch;
  433. while (ch = *pszValue++) {
  434. if (isdigit(ch) || ch==_T('+') || ch==_T('-')) {
  435. *pszDst++ = ch;
  436. }
  437. }
  438. *pszDst = 0;
  439. sStrippedValue.ReleaseBuffer();
  440. *plResult = _ttol(sStrippedValue);
  441. return S_OK;
  442. }