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.

701 lines
16 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1998 **/
  4. /**********************************************************************/
  5. /*
  6. format.cpp
  7. FILE HISTORY:
  8. */
  9. #include "stdafx.h"
  10. #include "tfschar.h"
  11. #include "mprapi.h"
  12. #include "rtrstr.h"
  13. #include "format.h"
  14. #include "raserror.h"
  15. #include "mprerror.h"
  16. //----------------------------------------------------------------------------
  17. // Function: FormatSystemError
  18. //
  19. // Formats an error code using '::FormatMessage', '::MprAdminGetErrorString',
  20. // or '::RasAdminGetErrorString', or all the above (the default).
  21. // If 'psFormat' is specified, it is used to format the error-string
  22. // into 'sError'.
  23. //----------------------------------------------------------------------------
  24. DWORD
  25. FormatSystemError(
  26. IN HRESULT hrErr,
  27. LPTSTR pszBuffer,
  28. UINT cchBuffer,
  29. IN UINT idsFormat,
  30. IN DWORD dwFormatFlags
  31. ) {
  32. DWORD dwErr = WIN32_FROM_HRESULT(hrErr);
  33. DWORD dwRet = NO_ERROR;
  34. TCHAR* pszErr = NULL;
  35. WCHAR* pwsErr = NULL;
  36. CString sError;
  37. dwFormatFlags &= FSEFLAG_ANYMESSAGE;
  38. do {
  39. //
  40. // See if 'FSEFLAG_MPRMESSAGE' is specified
  41. //
  42. if (dwFormatFlags & FSEFLAG_MPRMESSAGE)
  43. {
  44. dwFormatFlags &= ~FSEFLAG_MPRMESSAGE;
  45. if (((dwErr >= ROUTEBASE) && (dwErr <= ROUTEBASEEND)) ||
  46. ((dwErr >= RASBASE) && (dwErr <= RASBASEEND)))
  47. {
  48. //
  49. // Try retrieving a string from rasmsg.dll or mprmsg.dll
  50. //
  51. dwRet = ::MprAdminGetErrorString(dwErr, &pwsErr);
  52. if (dwRet == NO_ERROR)
  53. {
  54. pszErr = StrDupTFromW(pwsErr);
  55. ::MprAdminBufferFree(pwsErr);
  56. break;
  57. }
  58. else if (!dwFormatFlags)
  59. break;
  60. dwRet = NO_ERROR;
  61. }
  62. else if (!dwFormatFlags)
  63. return ERROR_INVALID_PARAMETER;
  64. }
  65. //
  66. // See if 'FSEFLAG_SYSMESSAGE' is specified
  67. //
  68. if (dwFormatFlags & FSEFLAG_SYSMESSAGE)
  69. {
  70. dwFormatFlags &= ~FSEFLAG_SYSMESSAGE;
  71. //
  72. // Try retrieving a string from the system
  73. //
  74. dwRet = ::FormatMessageW(
  75. FORMAT_MESSAGE_ALLOCATE_BUFFER|
  76. FORMAT_MESSAGE_FROM_SYSTEM,
  77. NULL,
  78. hrErr,
  79. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  80. (LPTSTR)&pwsErr,
  81. 1,
  82. NULL
  83. );
  84. if (dwRet)
  85. {
  86. pszErr = StrDupTFromW(pwsErr);
  87. LocalFree(pwsErr);
  88. break;
  89. }
  90. else if (!dwFormatFlags)
  91. break;
  92. dwRet = NO_ERROR;
  93. }
  94. } while (FALSE);
  95. //
  96. // If no string was found, format the error as a number.
  97. //
  98. if (!pszErr)
  99. {
  100. TCHAR szErr[12];
  101. wsprintf(szErr, TEXT("%d"), dwErr);
  102. pszErr = StrDup(szErr);
  103. }
  104. //
  105. // Format the string into the caller's argument
  106. //
  107. if (idsFormat)
  108. AfxFormatString1(sError, idsFormat, pszErr);
  109. else
  110. sError = pszErr;
  111. // Finally, copy the output
  112. StrnCpy(pszBuffer, (LPCTSTR) sError, cchBuffer);
  113. delete pszErr;
  114. return dwRet;
  115. }
  116. //
  117. // Forward declaration of utility function used by 'FormatNumber'
  118. //
  119. TCHAR*
  120. padultoa(
  121. UINT val,
  122. TCHAR* pszBuf,
  123. INT width
  124. );
  125. //----------------------------------------------------------------------------
  126. // Function: FormatNumber
  127. //
  128. // This function takes an integer and formats a string with the value
  129. // represented by the number, grouping digits by powers of one-thousand
  130. //----------------------------------------------------------------------------
  131. VOID
  132. FormatNumber(DWORD dwNumber,
  133. LPTSTR pszBuffer,
  134. UINT cchBuffer,
  135. BOOL fSigned)
  136. {
  137. Assert(cchBuffer > 14);
  138. static TCHAR szNegativeSign[4] = TEXT("");
  139. static TCHAR szThousandsSeparator[4] = TEXT("");
  140. DWORD i, dwLength;
  141. TCHAR szDigits[12] = {0}, pszTemp[20] = {0};
  142. //
  143. // Retrieve the thousands-separator for the user's locale
  144. //
  145. if (szThousandsSeparator[0] == TEXT('\0'))
  146. {
  147. ::GetLocaleInfo(
  148. LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandsSeparator, 4
  149. );
  150. }
  151. //
  152. // If we are formatting a signed value, see if the value is negative
  153. //
  154. if (fSigned)
  155. {
  156. if ((INT)dwNumber >= 0)
  157. fSigned = FALSE;
  158. else
  159. {
  160. //
  161. // The value is negative; retrieve the locale's negative-sign
  162. //
  163. if (szNegativeSign[0] == TEXT('\0')) {
  164. ::GetLocaleInfo(
  165. LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, szNegativeSign, 4
  166. );
  167. }
  168. dwNumber = abs((INT)dwNumber);
  169. }
  170. }
  171. //
  172. // Convert the number to a string without thousands-separators
  173. //
  174. padultoa(dwNumber, szDigits, 0);
  175. dwLength = lstrlen(szDigits);
  176. //
  177. // If the length of the string without separators is n,
  178. // then the length of the string with separators is n + (n - 1) / 3
  179. //
  180. i = dwLength;
  181. dwLength += (dwLength - 1) / 3;
  182. //
  183. // Write the number to the buffer in reverse
  184. //
  185. TCHAR* pszsrc, *pszdst;
  186. pszsrc = szDigits + i - 1; pszdst = pszTemp + dwLength;
  187. *pszdst-- = TEXT('\0');
  188. while (TRUE) {
  189. if (i--) { *pszdst-- = *pszsrc--; } else { break; }
  190. if (i--) { *pszdst-- = *pszsrc--; } else { break; }
  191. if (i--) { *pszdst-- = *pszsrc--; } else { break; }
  192. if (i) { *pszdst-- = *szThousandsSeparator; } else { break; }
  193. }
  194. pszBuffer[0] = 0;
  195. if (fSigned)
  196. lstrcat(pszBuffer, szNegativeSign);
  197. lstrcat(pszBuffer, pszTemp);
  198. }
  199. //----------------------------------------------------------------------------
  200. // Function: padultoa
  201. //
  202. // This functions formats the specified unsigned integer
  203. // into the specified string buffer, padding the buffer
  204. // so that it is at least the specified width.
  205. //
  206. // It is assumed that the buffer is at least wide enough
  207. // to contain the output, so this function does not truncate
  208. // the conversion result to the length of the 'width' parameter.
  209. //----------------------------------------------------------------------------
  210. TCHAR*
  211. padultoa(
  212. UINT val,
  213. TCHAR* pszBuf,
  214. INT width
  215. ) {
  216. TCHAR temp;
  217. PTSTR psz, zsp;
  218. psz = pszBuf;
  219. //
  220. // write the digits in reverse order
  221. //
  222. do {
  223. *psz++ = TEXT('0') + (val % 10);
  224. val /= 10;
  225. } while(val > 0);
  226. //
  227. // pad the string to the required width
  228. //
  229. zsp = pszBuf + width;
  230. while (psz < zsp) { *psz++ = TEXT('0'); }
  231. *psz-- = TEXT('\0');
  232. //
  233. // reverse the digits
  234. //
  235. for (zsp = pszBuf; zsp < psz; zsp++, psz--) {
  236. temp = *psz; *psz = *zsp; *zsp = temp;
  237. }
  238. //
  239. // return the result
  240. //
  241. return pszBuf;
  242. }
  243. //----------------------------------------------------------------------------
  244. // Function: FormatListString
  245. //
  246. // Formats a list of strings as a single string, using the list-separator
  247. // for the current-user's locale.
  248. //----------------------------------------------------------------------------
  249. VOID
  250. FormatListString(
  251. IN CStringList& strList,
  252. IN CString& sListString,
  253. IN LPCTSTR pszSeparator
  254. ) {
  255. static TCHAR szListSeparator[4] = TEXT("");
  256. POSITION pos;
  257. sListString.Empty();
  258. pos = strList.GetHeadPosition();
  259. while (pos) {
  260. //
  261. // Add the next string
  262. //
  263. sListString += strList.GetNext(pos);
  264. //
  265. // If any strings are left, append the list-separator
  266. //
  267. if (pos) {
  268. //
  269. // Load the list-separator if necessary
  270. //
  271. if (!pszSeparator && szListSeparator[0] == TEXT('\0')) {
  272. GetLocaleInfo(
  273. LOCALE_USER_DEFAULT, LOCALE_SLIST, szListSeparator, 4
  274. );
  275. lstrcat(szListSeparator, TEXT(" "));
  276. }
  277. //
  278. // Append the list-separator
  279. //
  280. sListString += (pszSeparator ? pszSeparator : szListSeparator);
  281. }
  282. }
  283. }
  284. //----------------------------------------------------------------------------
  285. // Function: FormatHexBytes
  286. //
  287. // Formats an array of bytes as a string.
  288. //----------------------------------------------------------------------------
  289. VOID
  290. FormatHexBytes(
  291. IN BYTE* pBytes,
  292. IN DWORD dwCount,
  293. IN CString& sBytes,
  294. IN TCHAR chDelimiter
  295. ) {
  296. TCHAR* psz;
  297. sBytes.Empty();
  298. if (!dwCount) { return; }
  299. psz = sBytes.GetBufferSetLength(dwCount * 3 + 1);
  300. for ( ; dwCount > 1; pBytes++, dwCount--) {
  301. *psz++ = c_szHexCharacters[*pBytes / 16];
  302. *psz++ = c_szHexCharacters[*pBytes % 16];
  303. *psz++ = chDelimiter;
  304. }
  305. *psz++ = c_szHexCharacters[*pBytes / 16];
  306. *psz++ = c_szHexCharacters[*pBytes % 16];
  307. *psz++ = TEXT('\0');
  308. sBytes.ReleaseBuffer();
  309. }
  310. /*!--------------------------------------------------------------------------
  311. DisplayErrorMessage
  312. -
  313. Author: KennT
  314. ---------------------------------------------------------------------------*/
  315. void DisplayErrorMessage(HWND hWndParent, HRESULT hr)
  316. {
  317. if (FHrSucceeded(hr))
  318. return;
  319. TCHAR szErr[2048];
  320. FormatSystemError(hr,
  321. szErr,
  322. DimensionOf(szErr),
  323. 0,
  324. FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE
  325. );
  326. AfxMessageBox(szErr);
  327. // ::MessageBox(hWndParent, szErr, NULL, MB_OK);
  328. }
  329. /*!--------------------------------------------------------------------------
  330. DisplayStringErrorMessage2
  331. -
  332. Author: KennT
  333. ---------------------------------------------------------------------------*/
  334. void DisplayStringErrorMessage2(HWND hWndParent, LPCTSTR pszTopLevelText, HRESULT hr)
  335. {
  336. if (FHrSucceeded(hr))
  337. return;
  338. TCHAR szText[4096];
  339. TCHAR szErr[2048];
  340. FormatSystemError(hr,
  341. szErr,
  342. DimensionOf(szErr),
  343. 0,
  344. FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE
  345. );
  346. StrnCpy(szText, pszTopLevelText, DimensionOf(szText));
  347. StrCat(szText, szErr);
  348. AfxMessageBox(szText);
  349. // ::MessageBox(hWndParent, szErr, NULL, MB_OK);
  350. }
  351. /*!--------------------------------------------------------------------------
  352. DisplayIdErrorMessage2
  353. -
  354. Author: KennT
  355. ---------------------------------------------------------------------------*/
  356. void DisplayIdErrorMessage2(HWND hWndParent, UINT idsError, HRESULT hr)
  357. {
  358. if (FHrSucceeded(hr))
  359. return;
  360. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  361. CString stError;
  362. TCHAR szErr[2048];
  363. stError.LoadString(idsError);
  364. FormatSystemError(hr,
  365. szErr,
  366. DimensionOf(szErr),
  367. 0,
  368. FSEFLAG_SYSMESSAGE | FSEFLAG_MPRMESSAGE
  369. );
  370. stError += szErr;
  371. AfxMessageBox(stError);
  372. // ::MessageBox(hWndParent, szErr, NULL, MB_OK);
  373. }
  374. //----------------------------------------------------------------------------
  375. // Function: FormatDuration
  376. //
  377. // Formats a number as a duration, using the time-separator
  378. // for the current-user's locale. dwBase is the number of units that make
  379. // up a second (if dwBase==1 then the input is seconds, if dwBase==1000 then
  380. // the input expected is in milliseconds.
  381. //----------------------------------------------------------------------------
  382. VOID
  383. FormatDuration(
  384. IN DWORD dwDuration,
  385. IN CString& sDuration,
  386. IN DWORD dwTimeBase,
  387. IN DWORD dwFormatFlags
  388. ) {
  389. static TCHAR szTimeSeparator[4] = TEXT("");
  390. TCHAR *psz, szOutput[64];
  391. sDuration.Empty();
  392. if ((dwFormatFlags & FDFLAG_ALL) == 0) { return; }
  393. //
  394. // Retrieve the time-separator if necessary
  395. //
  396. if (szTimeSeparator[0] == TEXT('\0')) {
  397. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, szTimeSeparator, 4);
  398. }
  399. //
  400. // Concatenate the strings for the duration-components together
  401. //
  402. psz = szOutput;
  403. szOutput[0] = TEXT('\0');
  404. dwFormatFlags &= FDFLAG_ALL;
  405. if (dwFormatFlags & FDFLAG_DAYS) {
  406. //
  407. // Format the number of days if requested
  408. //
  409. padultoa(dwDuration / (24 * 60 * 60 * dwTimeBase), psz, 0);
  410. dwDuration %= (24 * 60 * 60 * dwTimeBase);
  411. //
  412. // Append the time-separator
  413. //
  414. if (dwFormatFlags &= ~FDFLAG_DAYS) { lstrcat(psz, szTimeSeparator); }
  415. psz += lstrlen(psz);
  416. }
  417. if (dwFormatFlags & FDFLAG_HOURS) {
  418. //
  419. // Format the number of hours if requested
  420. //
  421. padultoa(dwDuration / (60 * 60 * dwTimeBase), psz, 2);
  422. dwDuration %= (60 * 60 * dwTimeBase);
  423. //
  424. // Append the time-separator
  425. //
  426. if (dwFormatFlags &= ~FDFLAG_HOURS) { lstrcat(psz, szTimeSeparator); }
  427. psz += lstrlen(psz);
  428. }
  429. if (dwFormatFlags & FDFLAG_MINUTES) {
  430. //
  431. // Format the number of minutes
  432. //
  433. padultoa(dwDuration / (60 * dwTimeBase), psz, 2);
  434. dwDuration %= (60 * dwTimeBase);
  435. //
  436. // Append the time separator
  437. //
  438. if (dwFormatFlags &= ~FDFLAG_MINUTES) { lstrcat(psz, szTimeSeparator); }
  439. psz += lstrlen(psz);
  440. }
  441. if (dwFormatFlags & FDFLAG_SECONDS) {
  442. //
  443. // Format the number of seconds
  444. //
  445. padultoa(dwDuration / dwTimeBase, psz, 2);
  446. dwDuration %= dwTimeBase;
  447. //
  448. // Append the time-separator
  449. //
  450. if (dwFormatFlags &= ~FDFLAG_SECONDS) { lstrcat(psz, szTimeSeparator); }
  451. psz += lstrlen(psz);
  452. }
  453. if (dwFormatFlags & FDFLAG_MSECONDS) {
  454. //
  455. // Format the number of milliseconds
  456. //
  457. padultoa(dwDuration % dwTimeBase, psz, 0); psz += lstrlen(psz);
  458. }
  459. sDuration = szOutput;
  460. }
  461. /*---------------------------------------------------------------------------
  462. IfIndexToNameMapping implementation
  463. ---------------------------------------------------------------------------*/
  464. IfIndexToNameMapping::IfIndexToNameMapping()
  465. {
  466. }
  467. IfIndexToNameMapping::~IfIndexToNameMapping()
  468. {
  469. // Iterate through the map and delete all the pointers
  470. POSITION pos;
  471. LPVOID pvKey, pvValue;
  472. for (pos = m_map.GetStartPosition(); pos; )
  473. {
  474. m_map.GetNextAssoc(pos, pvKey, pvValue);
  475. delete (CString *) pvValue;
  476. pvValue = NULL;
  477. m_map.SetAt(pvKey, pvValue);
  478. }
  479. m_map.RemoveAll();
  480. }
  481. /*!--------------------------------------------------------------------------
  482. IfIndexToNameMapping::Add
  483. -
  484. Author: KennT
  485. ---------------------------------------------------------------------------*/
  486. HRESULT IfIndexToNameMapping::Add(ULONG ulIndex, LPCTSTR pszName)
  487. {
  488. HRESULT hr = hrOK;
  489. LPVOID pvKey, pvValue;
  490. COM_PROTECT_TRY
  491. {
  492. pvKey = (LPVOID) ULongToPtr( ulIndex );
  493. pvValue = NULL;
  494. // If we can find the value, don't add it
  495. if (m_map.Lookup(pvKey, pvValue) == 0)
  496. {
  497. pvValue = (LPVOID) new CString(pszName);
  498. m_map.SetAt(pvKey, pvValue);
  499. }
  500. Assert(((CString *) pvValue)->CompareNoCase(pszName) == 0);
  501. }
  502. COM_PROTECT_CATCH;
  503. return hr;
  504. }
  505. /*!--------------------------------------------------------------------------
  506. IfIndexToNameMapping::Find
  507. -
  508. Author: KennT
  509. ---------------------------------------------------------------------------*/
  510. LPCTSTR IfIndexToNameMapping::Find(ULONG ulIndex)
  511. {
  512. LPVOID pvValue = NULL;
  513. if (m_map.Lookup((LPVOID) ULongToPtr(ulIndex), pvValue))
  514. return (LPCTSTR) *((CString *)pvValue);
  515. else
  516. return NULL;
  517. }