#include "stdafx.h" #include "utils.h" #include "globals.h" #include "trapreg.h" //*************************************************************************** // // MapEventToSeverity // // Extract the severity field from the event ID and convert it to a // string equivallent. // // Parameters: // DWORD dwEvent // The full event ID // // CString& sResult // The severity code string is returned here. // // Returns: // The severity code string is returned via sResult. // // Status: // //*************************************************************************** void MapEventToSeverity(DWORD dwEvent, CString& sResult) { // // Values are 32 bit event ID values layed out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 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 // +---+-+-+-----------------------+-------------------------------+ // |Sev|C|R| Facility | Code | // +---+-+-+-----------------------+-------------------------------+ // // where // // Sev - is the severity code // // 00 - Success // 01 - Informational // 10 - Warning // 11 - Error // // C - is the Customer code flag // // R - is a reserved bit // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes static UINT auiResource[4] = {IDS_EVENT_SEV_SUCCESS, IDS_EVENT_SEV_INFORMATIONAL, IDS_EVENT_SEV_WARNING, IDS_EVENT_SEV_ERROR }; int iSeverity = (dwEvent >> 30) & 3; sResult.LoadString(auiResource[iSeverity]); } //******************************************************************************** // FindSubstring // // Find a substring in some text and return an index to the starting // position of the string if it is found. // // Parameters: // LPCSTR pszTemplate // Pointer to the string to find. // // LPCSTR pszText // Pointer to the text that will be searched // for the template string. // // Returns: // An index to the location of the substring within the text if it // is found, otherwise -1. // //******************************************************************************** LONG FindSubstring(LPCTSTR pszTemplate, LPCTSTR pszText) { if (*pszTemplate == 0) { // An empty template string matches anything, so return zero. // This should never really happen since it doesn't make much // sense to search for nothing. return 0; } LPCTSTR pszTextStart = pszText; while (*pszText) { // Iterate through the character positions in the text // and return the index to the starting char in the string // if it is found. LPCTSTR pch1 = pszTemplate; LPCTSTR pch2 = pszText; while (*pch1 && (*pch1 == *pch2)) { ++pch1; ++pch2; } if (*pch1 == 0) { // We reached the end of the template string, so there // must have been a match. return (LONG)(pszText - pszTextStart); } ++pszText; } // Failed to find the substring return -1; } //******************************************************************************** // FindWholeWord // // Find a whole word in some text and return an index to the starting // position of the whole word if it is found. Whole word means the // specified template string followed by a whitespace or end of string. // // Parameters: // LPCSTR pszTemplate // Pointer to the "whole word" string to find. // // LPCSTR pszText // Pointer to the text that will be searched // for the template string. // // Returns: // An index to the location of the "whole word" substring within the text if it // is found, otherwise -1. // //******************************************************************************** LONG FindWholeWord(LPCTSTR pszTemplate, LPCTSTR pszText) { if (*pszTemplate == 0) { // An empty search string matches anything, so return the index // of the first character. return 0; } // Iterate through each character position checking for a whole-word // match at each position. LONG nchTemplate = _tcslen(pszTemplate); LPCTSTR pszTextStart = pszText; LPCTSTR pchTextLimit = pszText + (_tcslen(pszText) - nchTemplate); while (pszText <= pchTextLimit) { // Check to see if the word is contained anywhere within the text INT iPos = FindSubstring(pszTemplate, pszText); if (iPos == -1) { return -1; } // Point at the location of the template string within the text pszText += iPos; // Get the prefix character INT ichPrefix; if (pszText == pszTextStart) { // Beginning of line counts as white space. ichPrefix = _T(' '); } else { ichPrefix = *(pszText - 1); } // Get the suffix character. INT ichSuffix = pszText[nchTemplate]; if (ichSuffix == 0) { // End of line counts as whitespace ichSuffix = _T(' '); } // To match a whole word, the word must be bounded on either side // by whitespace. if (isspace(ichPrefix) && isspace(ichSuffix)) { return (LONG)(pszText - pszTextStart); } // Bump the text pointer to the next position so we don't do the // same thing all over again. ++pszText; } return -1; } void DecString(CString& sValue, int iValue) { // 32 bytes should be enough to hold any value TCHAR szValue[32]; _itot(iValue, szValue, 10); sValue = szValue; } void DecString(CString& sValue, long lValue) { // 32 bytes should be enough to hold any value TCHAR szValue[32]; _ltot(lValue, szValue, 10); sValue = szValue; } void DecString(CString& sValue, DWORD dwValue) { TCHAR szValue[32]; _ultot(dwValue, szValue, 10); sValue = szValue; } CList::CList() { m_pndPrev = this; m_pndNext = this; } void CList::Link(CList*& pndHead) { if (pndHead == NULL) pndHead = this; else { m_pndNext = pndHead; m_pndPrev = pndHead->m_pndPrev; m_pndPrev->m_pndNext = this; m_pndNext->m_pndPrev = this; } } void CList::Unlink(CList*& pndHead) { if (pndHead == this) { if (m_pndNext == this) pndHead = NULL; else pndHead = m_pndNext; } m_pndPrev->m_pndNext = m_pndNext; m_pndNext->m_pndPrev = m_pndPrev; } //*************************************************************** // GetFormattedValue // // Convert a value to ASCII and insert thousand separator characters // into resulting value string. // // Parameters: // CString& sValueDst // The place to return the converted value. // // LONG lValue // The value to convert. // //***************************************************************** void GetFormattedValue(CString& sValueDst, LONG lValue) { CString sValueSrc; DecString(sValueSrc, lValue); LONG nch = sValueSrc.GetLength(); LPCTSTR pszSrc = sValueSrc; // Get a buffer as large as the source string plus the largest number of commas // plus one for the sign, one for the null terminator plus one character for slop. LPTSTR pszDst = sValueDst.GetBuffer(nch + nch / 3 + 3); // Copy any leading sign character. if ((*pszSrc == _T('+')) || (*pszSrc == _T('-'))) { *pszDst++ = *pszSrc++; --nch; } // Now copy the rest of the number and insert thousand separator characters in // the appropriate positions. LONG nchInitial = nch; while (nch > 0) { if ((nch % 3) == 0) { if (nch != nchInitial) { *pszDst++ = g_chThousandSep; } } *pszDst++ = *pszSrc++; --nch; } *pszDst = _T('\0'); sValueDst.ReleaseBuffer(); } //************************************************************** // GenerateRangeMessage // // Generate a message indicating that the user should enter a value // between some numbers nMin and nMax. // // Parameters: // CString& sMessage // The place to return the message. // // LONG nMin // The minimum valid value in the range. // // LONG nMax // The maximum valid value in the range. // //**************************************************************** void GenerateRangeMessage(CString& sMessage, LONG nMin, LONG nMax) { CString sText; sMessage.LoadString(IDS_RANGE_MESSAGE_PREFIX); sMessage += _T(' '); GetFormattedValue(sText, nMin); sMessage += sText; sMessage += _T(' '); sText.LoadString(IDS_RANGE_VALUE_SEPARATOR); sMessage += sText; sMessage += _T(' '); GetFormattedValue(sText, nMax); sMessage += sText; sText.LoadString(IDS_SENTENCE_TERMINATOR); sMessage += sText; } //*************************************************************************** // GetThousandSeparator // // Get the thousand separator character for the current locale. // // Parameters: // TCHAR* pchThousandSep // Pointer to the place to return the thousand separator character. // // Returns: // SCODE // S_OK if the thousand separator was returned. // E_FAIL if the thousand separator was not returned. // //************************************************************************** SCODE GetThousandSeparator(TCHAR* pchThousandSep) { // Digit + separator + 3 digits + decimal + two digits + null terminator + 4 slop #define MAX_CHARS_THOUSAND 12 CString sValue; LPTSTR pszValue = sValue.GetBuffer(MAX_CHARS_THOUSAND); GetNumberFormat(NULL, 0, _T("1000"), NULL, pszValue, MAX_CHARS_THOUSAND); sValue.ReleaseBuffer(); TCHAR ch = sValue[1]; if (isdigit(ch)) { return E_FAIL; } *pchThousandSep = ch; return S_OK; } //*********************************************************************** // IsDecimalInteger // // This function tests a string to see whether or not it contains a // valid integer expression. // // Parameters: // LPCTSTR pszValue // Pointer to the string to test. // // Returns: // BOOL // TRUE = The string contained a valid integer expression. // FALSE = The string did not contain a valid integer expression. // //*********************************************************************** BOOL IsDecimalInteger(LPCTSTR pszValue) { // Accept leading white space while (iswspace(*pszValue)) { ++pszValue; } // Accept a leading plus or minus sign if ((*pszValue == _T('+')) || (*pszValue == _T('-'))) { ++pszValue; } // Skip a string of consecutive digits with embedded thousand separators BOOL bSawThousandSep = FALSE; LONG nDigits = 0; while (TRUE) { if (*pszValue == g_chThousandSep) { if (nDigits > 3) { return FALSE; } bSawThousandSep = TRUE; nDigits = 0; } else if (isdigit(*pszValue)) { ++nDigits; } else { break; } ++pszValue; } if (bSawThousandSep && nDigits != 3) { // If a thousand separater was encountered, then there must be // three digits to the right of the last thousand separator. return FALSE; } // Accept trailing whitespace if (iswspace(*pszValue)) { ++pszValue; } if (*pszValue == _T('\0')) { // We reached the end of the string, so it must have been a decimal integer. return TRUE; } else { // We did not rech the end of the string, so it couldn't have been a valid // decimal integer value. return FALSE; } } //*************************************************************************** // AsciiToLong // // This function first validates a string to make sure that it is a properly // formatted integer expression, and then converts it to a long. Any embedded // characters, such as the thousand separator, are stripped out before the // conversion is done. // // // Parameters: // LPCTSTR pszValue // Pointer to the string value to convert. // // LONG* plResult // Pointer to the place to store the result. // // Returns: // SCODE // S_OK = The string contained a valid integer and the converted // value was returned via plResult. // E_FAIL = The string did not contain a properly formatted integer // expression. // // //************************************************************************** SCODE AsciiToLong(LPCTSTR pszValue, LONG* plResult) { if (!IsDecimalInteger(pszValue)) { return E_FAIL; } // Strip out any superfluous characters, such as the thousand separator // before converting from ascii to long. CString sStrippedValue; LPTSTR pszDst = sStrippedValue.GetBuffer(_tcslen(pszValue) + 1); TCHAR ch; while (ch = *pszValue++) { if (isdigit(ch) || ch==_T('+') || ch==_T('-')) { *pszDst++ = ch; } } *pszDst = 0; sStrippedValue.ReleaseBuffer(); *plResult = _ttol(sStrippedValue); return S_OK; }