/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1998 **/ /**********************************************************************/ /* format.cpp FILE HISTORY: */ #include "stdafx.h" #include "tfschar.h" #include "mprapi.h" #include "rtrstr.h" #include "format.h" #include "raserror.h" #include "mprerror.h" //---------------------------------------------------------------------------- // Function: FormatSystemError // // Formats an error code using '::FormatMessage', '::MprAdminGetErrorString', // or '::RasAdminGetErrorString', or all the above (the default). // If 'psFormat' is specified, it is used to format the error-string // into 'sError'. //---------------------------------------------------------------------------- DWORD FormatSystemError( IN HRESULT hrErr, LPTSTR pszBuffer, UINT cchBuffer, IN UINT idsFormat, IN DWORD dwFormatFlags ) { DWORD dwErr = WIN32_FROM_HRESULT(hrErr); DWORD dwRet; TCHAR* pszErr = NULL; WCHAR* pwsErr = NULL; CString sError; dwFormatFlags &= FSEFLAG_ANYMESSAGE; do { // // See if 'FSEFLAG_MPRMESSAGE' is specified // if (dwFormatFlags & FSEFLAG_MPRMESSAGE) { dwFormatFlags &= ~FSEFLAG_MPRMESSAGE; if (((dwErr >= ROUTEBASE) && (dwErr <= ROUTEBASEEND)) || ((dwErr >= RASBASE) && (dwErr <= RASBASEEND))) { // // Try retrieving a string from rasmsg.dll or mprmsg.dll // dwRet = ::MprAdminGetErrorString(dwErr, &pwsErr); if (dwRet == NO_ERROR) { pszErr = StrDupTFromW(pwsErr); ::MprAdminBufferFree(pwsErr); break; } else if (!dwFormatFlags) break; dwRet = NO_ERROR; } else if (!dwFormatFlags) return ERROR_INVALID_PARAMETER; } // // See if 'FSEFLAG_SYSMESSAGE' is specified // if (dwFormatFlags & FSEFLAG_SYSMESSAGE) { dwFormatFlags &= ~FSEFLAG_SYSMESSAGE; // // Try retrieving a string from the system // dwRet = ::FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM, NULL, hrErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pwsErr, 1, NULL ); if (dwRet) { pszErr = StrDupTFromW(pwsErr); LocalFree(pwsErr); break; } else if (!dwFormatFlags) break; dwRet = NO_ERROR; } } while (FALSE); // // If no string was found, format the error as a number. // if (!pszErr) { TCHAR szErr[12]; wsprintf(szErr, TEXT("%d"), dwErr); pszErr = StrDup(szErr); } // // Format the string into the caller's argument // if (idsFormat) AfxFormatString1(sError, idsFormat, pszErr); else sError = pszErr; // Finally, copy the output StrnCpy(pszBuffer, (LPCTSTR) sError, cchBuffer); delete pszErr; return dwRet; } // // Forward declaration of utility function used by 'FormatNumber' // TCHAR* padultoa( UINT val, TCHAR* pszBuf, INT width ); //---------------------------------------------------------------------------- // Function: FormatNumber // // This function takes an integer and formats a string with the value // represented by the number, grouping digits by powers of one-thousand //---------------------------------------------------------------------------- VOID FormatNumber(DWORD dwNumber, LPTSTR pszBuffer, UINT cchBuffer, BOOL fSigned) { Assert(cchBuffer > 14); static TCHAR szNegativeSign[4] = TEXT(""); static TCHAR szThousandsSeparator[4] = TEXT(""); DWORD i, dwLength; TCHAR szDigits[12] = {0}, pszTemp[20] = {0}; // // Retrieve the thousands-separator for the user's locale // if (szThousandsSeparator[0] == TEXT('\0')) { ::GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandsSeparator, 4 ); } // // If we are formatting a signed value, see if the value is negative // if (fSigned) { if ((INT)dwNumber >= 0) fSigned = FALSE; else { // // The value is negative; retrieve the locale's negative-sign // if (szNegativeSign[0] == TEXT('\0')) { ::GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, szNegativeSign, 4 ); } dwNumber = abs((INT)dwNumber); } } // // Convert the number to a string without thousands-separators // padultoa(dwNumber, szDigits, 0); dwLength = lstrlen(szDigits); // // If the length of the string without separators is n, // then the length of the string with separators is n + (n - 1) / 3 // i = dwLength; dwLength += (dwLength - 1) / 3; // // Write the number to the buffer in reverse // TCHAR* pszsrc, *pszdst; pszsrc = szDigits + i - 1; pszdst = pszTemp + dwLength; *pszdst-- = TEXT('\0'); while (TRUE) { if (i--) { *pszdst-- = *pszsrc--; } else { break; } if (i--) { *pszdst-- = *pszsrc--; } else { break; } if (i--) { *pszdst-- = *pszsrc--; } else { break; } if (i) { *pszdst-- = *szThousandsSeparator; } else { break; } } pszBuffer[0] = 0; if (fSigned) lstrcat(pszBuffer, szNegativeSign); lstrcat(pszBuffer, pszTemp); } //---------------------------------------------------------------------------- // Function: padultoa // // This functions formats the specified unsigned integer // into the specified string buffer, padding the buffer // so that it is at least the specified width. // // It is assumed that the buffer is at least wide enough // to contain the output, so this function does not truncate // the conversion result to the length of the 'width' parameter. //---------------------------------------------------------------------------- TCHAR* padultoa( UINT val, TCHAR* pszBuf, INT width ) { TCHAR temp; PTSTR psz, zsp; psz = pszBuf; // // write the digits in reverse order // do { *psz++ = TEXT('0') + (val % 10); val /= 10; } while(val > 0); // // pad the string to the required width // zsp = pszBuf + width; while (psz < zsp) { *psz++ = TEXT('0'); } *psz-- = TEXT('\0'); // // reverse the digits // for (zsp = pszBuf; zsp < psz; zsp++, psz--) { temp = *psz; *psz = *zsp; *zsp = temp; } // // return the result // return pszBuf; } //---------------------------------------------------------------------------- // Function: FormatListString // // Formats a list of strings as a single string, using the list-separator // for the current-user's locale. //---------------------------------------------------------------------------- VOID FormatListString( IN CStringList& strList, IN CString& sListString, IN LPCTSTR pszSeparator ) { static TCHAR szListSeparator[4] = TEXT(""); POSITION pos; sListString.Empty(); pos = strList.GetHeadPosition(); while (pos) { // // Add the next string // sListString += strList.GetNext(pos); // // If any strings are left, append the list-separator // if (pos) { // // Load the list-separator if necessary // if (!pszSeparator && szListSeparator[0] == TEXT('\0')) { GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SLIST, szListSeparator, 4 ); lstrcat(szListSeparator, TEXT(" ")); } // // Append the list-separator // sListString += (pszSeparator ? pszSeparator : szListSeparator); } } } //---------------------------------------------------------------------------- // Function: FormatHexBytes // // Formats an array of bytes as a string. //---------------------------------------------------------------------------- VOID FormatHexBytes( IN BYTE* pBytes, IN DWORD dwCount, IN CString& sBytes, IN TCHAR chDelimiter ) { TCHAR* psz; sBytes.Empty(); if (!dwCount) { return; } psz = sBytes.GetBufferSetLength(dwCount * 3 + 1); for ( ; dwCount > 1; pBytes++, dwCount--) { *psz++ = c_szHexCharacters[*pBytes / 16]; *psz++ = c_szHexCharacters[*pBytes % 16]; *psz++ = chDelimiter; } *psz++ = c_szHexCharacters[*pBytes / 16]; *psz++ = c_szHexCharacters[*pBytes % 16]; *psz++ = TEXT('\0'); sBytes.ReleaseBuffer(); } /*!-------------------------------------------------------------------------- DisplayErrorMessage - Author: KennT ---------------------------------------------------------------------------*/ void DisplayErrorMessage(HWND hWndParent, HRESULT hr) { if (FHrSucceeded(hr)) return; TCHAR szErr[2048]; FormatSystemError(hr, szErr, DimensionOf(szErr), 0, FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE ); AfxMessageBox(szErr); // ::MessageBox(hWndParent, szErr, NULL, MB_OK); } /*!-------------------------------------------------------------------------- DisplayStringErrorMessage2 - Author: KennT ---------------------------------------------------------------------------*/ void DisplayStringErrorMessage2(HWND hWndParent, LPCTSTR pszTopLevelText, HRESULT hr) { if (FHrSucceeded(hr)) return; TCHAR szText[4096]; TCHAR szErr[2048]; FormatSystemError(hr, szErr, DimensionOf(szErr), 0, FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE ); StrnCpy(szText, pszTopLevelText, DimensionOf(szText)); StrCat(szText, szErr); AfxMessageBox(szText); // ::MessageBox(hWndParent, szErr, NULL, MB_OK); } /*!-------------------------------------------------------------------------- DisplayIdErrorMessage2 - Author: KennT ---------------------------------------------------------------------------*/ void DisplayIdErrorMessage2(HWND hWndParent, UINT idsError, HRESULT hr) { if (FHrSucceeded(hr)) return; AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString stError; TCHAR szErr[2048]; stError.LoadString(idsError); FormatSystemError(hr, szErr, DimensionOf(szErr), 0, FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE ); stError += szErr; AfxMessageBox(stError); // ::MessageBox(hWndParent, szErr, NULL, MB_OK); } //---------------------------------------------------------------------------- // Function: FormatDuration // // Formats a number as a duration, using the time-separator // for the current-user's locale. dwBase is the number of units that make // up a second (if dwBase==1 then the input is seconds, if dwBase==1000 then // the input expected is in milliseconds. //---------------------------------------------------------------------------- VOID FormatDuration( IN DWORD dwDuration, IN CString& sDuration, IN DWORD dwTimeBase, IN DWORD dwFormatFlags ) { static TCHAR szTimeSeparator[4] = TEXT(""); TCHAR *psz, szOutput[64]; sDuration.Empty(); if ((dwFormatFlags & FDFLAG_ALL) == 0) { return; } // // Retrieve the time-separator if necessary // if (szTimeSeparator[0] == TEXT('\0')) { GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, szTimeSeparator, 4); } // // Concatenate the strings for the duration-components together // psz = szOutput; szOutput[0] = TEXT('\0'); dwFormatFlags &= FDFLAG_ALL; if (dwFormatFlags & FDFLAG_DAYS) { // // Format the number of days if requested // padultoa(dwDuration / (24 * 60 * 60 * dwTimeBase), psz, 0); dwDuration %= (24 * 60 * 60 * dwTimeBase); // // Append the time-separator // if (dwFormatFlags &= ~FDFLAG_DAYS) { lstrcat(psz, szTimeSeparator); } psz += lstrlen(psz); } if (dwFormatFlags & FDFLAG_HOURS) { // // Format the number of hours if requested // padultoa(dwDuration / (60 * 60 * dwTimeBase), psz, 2); dwDuration %= (60 * 60 * dwTimeBase); // // Append the time-separator // if (dwFormatFlags &= ~FDFLAG_HOURS) { lstrcat(psz, szTimeSeparator); } psz += lstrlen(psz); } if (dwFormatFlags & FDFLAG_MINUTES) { // // Format the number of minutes // padultoa(dwDuration / (60 * dwTimeBase), psz, 2); dwDuration %= (60 * dwTimeBase); // // Append the time separator // if (dwFormatFlags &= ~FDFLAG_MINUTES) { lstrcat(psz, szTimeSeparator); } psz += lstrlen(psz); } if (dwFormatFlags & FDFLAG_SECONDS) { // // Format the number of seconds // padultoa(dwDuration / dwTimeBase, psz, 2); dwDuration %= dwTimeBase; // // Append the time-separator // if (dwFormatFlags &= ~FDFLAG_SECONDS) { lstrcat(psz, szTimeSeparator); } psz += lstrlen(psz); } if (dwFormatFlags & FDFLAG_MSECONDS) { // // Format the number of milliseconds // padultoa(dwDuration % dwTimeBase, psz, 0); psz += lstrlen(psz); } sDuration = szOutput; } /*--------------------------------------------------------------------------- IfIndexToNameMapping implementation ---------------------------------------------------------------------------*/ IfIndexToNameMapping::IfIndexToNameMapping() { } IfIndexToNameMapping::~IfIndexToNameMapping() { // Iterate through the map and delete all the pointers POSITION pos; LPVOID pvKey, pvValue; for (pos = m_map.GetStartPosition(); pos; ) { m_map.GetNextAssoc(pos, pvKey, pvValue); delete (CString *) pvValue; pvValue = NULL; m_map.SetAt(pvKey, pvValue); } m_map.RemoveAll(); } /*!-------------------------------------------------------------------------- IfIndexToNameMapping::Add - Author: KennT ---------------------------------------------------------------------------*/ HRESULT IfIndexToNameMapping::Add(ULONG ulIndex, LPCTSTR pszName) { HRESULT hr = hrOK; LPVOID pvKey, pvValue; COM_PROTECT_TRY { pvKey = (LPVOID) ULongToPtr( ulIndex ); pvValue = NULL; // If we can find the value, don't add it if (m_map.Lookup(pvKey, pvValue) == 0) { pvValue = (LPVOID) new CString(pszName); m_map.SetAt(pvKey, pvValue); } Assert(((CString *) pvValue)->CompareNoCase(pszName) == 0); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- IfIndexToNameMapping::Find - Author: KennT ---------------------------------------------------------------------------*/ LPCTSTR IfIndexToNameMapping::Find(ULONG ulIndex) { LPVOID pvValue = NULL; if (m_map.Lookup((LPVOID) ULongToPtr(ulIndex), pvValue)) return (LPCTSTR) *((CString *)pvValue); else return NULL; }