Source code of Windows XP (NT5)
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.

1495 lines
27 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. msg.cpp
  5. Abstract:
  6. Message Functions
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include <lmerr.h>
  15. #include <lmcons.h>
  16. #include <winsock2.h>
  17. #include "comprop.h"
  18. #include <pudebug.h>
  19. #ifdef _MT
  20. //
  21. // Thread protected stuff
  22. //
  23. // (use code chunk below for tracing)
  24. // CString buf;\
  25. // buf.Format(_T("LowerThreadProtection at line %d in %S\n"), __LINE__, __FILE__);\
  26. // OutputDebugString(buf);
  27. #define RaiseThreadProtection() \
  28. do {\
  29. EnterCriticalSection(&_csSect);\
  30. } while(0)
  31. #define LowerThreadProtection() \
  32. do {\
  33. LeaveCriticalSection(&_csSect);\
  34. } while (0)
  35. static CRITICAL_SECTION _csSect;
  36. #else
  37. #pragma message("Module is not thread-safe.")
  38. #define RaiseThreadProtection()
  39. #define LowerThreadProtection()
  40. #endif // _MT
  41. BOOL
  42. InitErrorFunctionality()
  43. /*++
  44. Routine Description:
  45. Initialize CError class, and allocate static objects
  46. Arguments:
  47. None:
  48. Return Value:
  49. TRUE for success, FALSE for failure
  50. --*/
  51. {
  52. #ifdef _MT
  53. INITIALIZE_CRITICAL_SECTION(&_csSect);
  54. #endif // _MT
  55. return CError::AllocateStatics();
  56. }
  57. void
  58. TerminateErrorFunctionality()
  59. /*++
  60. Routine Description:
  61. De-initialize CError class, freeing up static objects
  62. Arguments:
  63. None
  64. Return Value:
  65. None
  66. --*/
  67. {
  68. CError::DeAllocateStatics();
  69. #ifdef _MT
  70. DeleteCriticalSection(&_csSect);
  71. #endif // _MT
  72. }
  73. //
  74. // Static Initialization:
  75. //
  76. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  77. const TCHAR g_cszNull[] = _T("(Null)");
  78. const TCHAR CError::s_chEscape = _T('%'); // Error text escape
  79. const TCHAR CError::s_chEscText = _T('h'); // Escape code for text
  80. const TCHAR CError::s_chEscNumber = _T('H'); // Escape code for error code
  81. LPCTSTR CError::s_cszLMDLL = _T("netmsg.dll"); // LM Error File
  82. LPCTSTR CError::s_cszWSDLL = _T("iisui.dll"); // Winsock error file
  83. LPCTSTR CError::s_cszFacility[] =
  84. {
  85. /* FACILITY_NULL */ NULL,
  86. /* FACILITY_RPC */ NULL,
  87. /* FACILITY_DISPATCH */ NULL,
  88. /* FACILITY_STORAGE */ NULL,
  89. /* FACILITY_ITF */ NULL,
  90. /* FACILITY_DS */ NULL,
  91. /* 6 */ NULL,
  92. /* FACILITY_WIN32 */ NULL,
  93. /* FACILITY_WINDOWS */ NULL,
  94. /* FACILITY_SSPI */ NULL,
  95. /* FACILITY_CONTROL */ NULL,
  96. /* FACILITY_CERT */ NULL,
  97. /* FACILITY_INTERNET */ _T("metadata.dll"),
  98. /* FACILITY_MEDIASERVER */ NULL,
  99. /* FACILITY_MSMQ */ NULL,
  100. /* FACILITY_SETUPAPI */ NULL,
  101. /* FACILITY_SCARD */ NULL,
  102. /* 17 (MTX) */ _T("iisui.dll"),
  103. };
  104. HRESULT CError::s_cdwMinLMErr = NERR_BASE;
  105. HRESULT CError::s_cdwMaxLMErr = MAX_NERR;
  106. HRESULT CError::s_cdwMinWSErr = WSABASEERR;
  107. HRESULT CError::s_cdwMaxWSErr = WSABASEERR + 2000;
  108. DWORD CError::s_cdwFacilities = (sizeof(CError::s_cszFacility)\
  109. / sizeof(CError::s_cszFacility[0]));
  110. //
  111. // Allocated objects (static MFC objects in a DLL are a no-no)
  112. //
  113. CString * CError::s_pstrDefError;
  114. CString * CError::s_pstrDefSuccs;
  115. CMapHRESULTtoUINT * CError::s_pmapOverrides;
  116. CMapDWORDtoCString * CError::s_pmapFacilities;
  117. BOOL CError::s_fAllocated = FALSE;
  118. /* protected */
  119. /* static */
  120. BOOL
  121. CError::AllocateStatics()
  122. /*++
  123. Routine Description:
  124. Allocate static objects
  125. Arguments:
  126. None
  127. Return Value:
  128. TRUE for successfull allocation, FALSE otherwise
  129. --*/
  130. {
  131. RaiseThreadProtection();
  132. if (!AreStaticsAllocated())
  133. {
  134. try
  135. {
  136. CError::s_pstrDefError = new CString;
  137. CError::s_pstrDefSuccs = new CString(_T("0x%08lx"));
  138. CError::s_pmapOverrides = new CMapHRESULTtoUINT;
  139. CError::s_pmapFacilities = new CMapDWORDtoCString;
  140. s_fAllocated = TRUE;
  141. LPTSTR lp = CError::s_pstrDefError->GetBuffer(255);
  142. if (!::LoadString(
  143. hDLLInstance,
  144. IDS_NO_MESSAGE,
  145. lp,
  146. 255
  147. ))
  148. {
  149. //
  150. // Just in case...
  151. //
  152. ASSERT(FALSE);
  153. lstrcpy(lp, _T("Error Code: 0x%08lx"));
  154. }
  155. CError::s_pstrDefError->ReleaseBuffer();
  156. }
  157. catch(CMemoryException * e)
  158. {
  159. TRACEEOLID("Initialization Failed");
  160. e->ReportError();
  161. e->Delete();
  162. }
  163. }
  164. LowerThreadProtection();
  165. return AreStaticsAllocated();
  166. }
  167. /* protected */
  168. /* static */
  169. void
  170. CError::DeAllocateStatics()
  171. /*++
  172. Routine Description:
  173. Clean up allocations
  174. Arguments:
  175. N/A
  176. Return Value:
  177. N/A
  178. --*/
  179. {
  180. RaiseThreadProtection();
  181. if (AreStaticsAllocated())
  182. {
  183. SAFE_DELETE(CError::s_pstrDefError);
  184. SAFE_DELETE(CError::s_pstrDefSuccs);
  185. SAFE_DELETE(CError::s_pmapOverrides);
  186. SAFE_DELETE(CError::s_pmapFacilities);
  187. s_fAllocated = FALSE;
  188. }
  189. LowerThreadProtection();
  190. }
  191. /* static */
  192. HRESULT
  193. CError::CvtToInternalFormat(
  194. IN HRESULT hrCode
  195. )
  196. /*++
  197. Routine Description:
  198. Convert WIN32 or HRESULT code to internal (HRESULT) format.
  199. Arguments:
  200. DWORD dwCode Error code
  201. Return Value:
  202. HRESULT
  203. Notes:
  204. HRESULTS are left as is. Lanman and Winsock errors are converted
  205. to HRESULTS using private facility codes.
  206. --*/
  207. {
  208. if (IS_HRESULT(hrCode))
  209. {
  210. return hrCode;
  211. }
  212. if(hrCode >= s_cdwMinLMErr && hrCode <= s_cdwMaxLMErr)
  213. {
  214. return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_LANMAN, (DWORD)hrCode);
  215. }
  216. if (hrCode >= s_cdwMinWSErr && hrCode <= s_cdwMaxWSErr)
  217. {
  218. return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WINSOCK, (DWORD)hrCode);
  219. }
  220. return HResult(hrCode);
  221. }
  222. //
  223. // Not publically defined in MFC
  224. //
  225. int AFXAPI AfxLoadString(UINT nIDS, LPTSTR lpszBuf, UINT nMaxBuf = 256);
  226. /* static */
  227. HRESULT
  228. CError::TextFromHRESULT(
  229. IN HRESULT hrCode,
  230. OUT LPTSTR szBuffer,
  231. OUT DWORD cchBuffer
  232. )
  233. /*++
  234. Routine Description:
  235. Get text from the given HRESULT. Based on the range that the HRESULT
  236. falls in and the facility code, find the location of the message,
  237. and fetch it.
  238. Arguments:
  239. HRESULT hrCode HRESULT or (DWORD WIN32 error) whose message to get
  240. LPTSTR szBuffer Buffer to load message text into
  241. DWORD cchBuffer Size of buffer in characters.
  242. Return Value:
  243. HRESULT error code depending on whether the message was
  244. found. If the message was not found, some generic message
  245. is synthesized in the buffer if a buffer is provided.
  246. ERROR_FILE_NOT_FOUND No message found
  247. ERROR_INSUFFICIENT_BUFFER Buffer is a NULL pointer or too small
  248. --*/
  249. {
  250. HRESULT hrReturn = ERROR_SUCCESS;
  251. //
  252. // First check to see if this message is overridden
  253. //
  254. UINT nID;
  255. if (HasOverride(hrCode, &nID))
  256. {
  257. //
  258. // Message overridden. Load replacement message
  259. // instead.
  260. //
  261. HINSTANCE hInstance = ::AfxGetResourceHandle();
  262. BOOL fSuccess;
  263. if (hInstance == NULL)
  264. {
  265. //
  266. // Console app
  267. //
  268. fSuccess = ::LoadString(
  269. ::GetModuleHandle(NULL),
  270. nID,
  271. szBuffer,
  272. cchBuffer
  273. );
  274. }
  275. else
  276. {
  277. //
  278. // MFC app
  279. //
  280. fSuccess = ::AfxLoadString(
  281. nID,
  282. szBuffer,
  283. cchBuffer
  284. );
  285. }
  286. if (fSuccess)
  287. {
  288. //
  289. // Everything ok
  290. //
  291. return hrReturn;
  292. }
  293. //
  294. // Message didn't exist, skip the override, and
  295. // load as normal.
  296. //
  297. TRACEEOLID("Attempted override failed. Couldn't load " << nID);
  298. ASSERT(FALSE);
  299. }
  300. LPCTSTR lpDll = NULL;
  301. HINSTANCE hDll = NULL;
  302. DWORD dwFacility = HRESULT_FACILITY(hrCode);
  303. DWORD dwSeverity = HRESULT_SEVERITY(hrCode);
  304. DWORD dwCode = HRESULT_CODE(hrCode);
  305. BOOL fSuccess = Succeeded(hrCode);
  306. //
  307. // Strip off meaningless internal facility codes
  308. //
  309. if (dwFacility == FACILITY_LANMAN || dwFacility == FACILITY_WINSOCK)
  310. {
  311. dwFacility = FACILITY_NULL;
  312. hrCode = (HRESULT)dwCode;
  313. }
  314. DWORD dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS |
  315. FORMAT_MESSAGE_MAX_WIDTH_MASK;
  316. //
  317. // Since we allow both HRESULTS and WIN32 codes to be
  318. // used here, we can't rely on the private FACILITY code
  319. // for lanman and winsock.
  320. //
  321. if(hrCode >= s_cdwMinLMErr && hrCode <= s_cdwMaxLMErr)
  322. {
  323. //
  324. // Lanman error
  325. //
  326. lpDll = s_cszLMDLL;
  327. }
  328. else if (hrCode >= s_cdwMinWSErr && hrCode <= s_cdwMaxWSErr)
  329. {
  330. //
  331. // Winsock error
  332. //
  333. lpDll = s_cszWSDLL;
  334. }
  335. else
  336. {
  337. //
  338. // Attempt to determine message location from facility code.
  339. // Check for registered facility first.
  340. //
  341. lpDll = FindFacility(dwFacility);
  342. if (lpDll == NULL)
  343. {
  344. if (dwFacility < s_cdwFacilities)
  345. {
  346. lpDll = s_cszFacility[dwFacility];
  347. }
  348. else
  349. {
  350. TRACEEOLID("Bogus FACILITY code encountered.");
  351. ASSERT(FALSE);
  352. lpDll = NULL;
  353. }
  354. }
  355. }
  356. do
  357. {
  358. if (szBuffer == NULL || cchBuffer <= 0)
  359. {
  360. hrReturn = HResult(ERROR_INSUFFICIENT_BUFFER);
  361. break;
  362. }
  363. if (lpDll)
  364. {
  365. //
  366. // Load message file
  367. //
  368. hDll = ::LoadLibraryEx(
  369. lpDll,
  370. NULL,
  371. LOAD_LIBRARY_AS_DATAFILE
  372. );
  373. if (hDll == NULL)
  374. {
  375. hrReturn = ::GetLastHRESULT();
  376. break;
  377. }
  378. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  379. }
  380. else
  381. {
  382. dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
  383. }
  384. DWORD dwResult = 0L;
  385. DWORD dwID = hrCode;
  386. HINSTANCE hSource = hDll;
  387. while(!dwResult)
  388. {
  389. dwResult = ::FormatMessage(
  390. dwFlags,
  391. (LPVOID)hSource,
  392. dwID,
  393. 0,
  394. szBuffer,
  395. cchBuffer,
  396. NULL
  397. );
  398. if (dwResult > 0)
  399. {
  400. //
  401. // Successfully got a message
  402. //
  403. hrReturn = ERROR_SUCCESS;
  404. break;
  405. }
  406. hrReturn = ::GetLastHRESULT();
  407. if (dwID != dwCode && !fSuccess)
  408. {
  409. //
  410. // Try the SCODE portion of the error from win32
  411. // if this is an error message
  412. //
  413. dwID = dwCode;
  414. hSource = NULL;
  415. continue;
  416. }
  417. //
  418. // Failed to obtain a message
  419. //
  420. hrReturn = HResult(ERROR_FILE_NOT_FOUND);
  421. break;
  422. }
  423. }
  424. while(FALSE);
  425. if(hDll != NULL)
  426. {
  427. ::FreeLibrary(hDll);
  428. }
  429. if (Failed(hrReturn))
  430. {
  431. //
  432. // Unable to find the message, synthesize something with
  433. // the code in it if there's room (+8 for the number)
  434. //
  435. CString & strMsg = (fSuccess ? *s_pstrDefSuccs : *s_pstrDefError);
  436. if (cchBuffer > (DWORD)strMsg.GetLength() + 8)
  437. {
  438. TRACEEOLID("Substituting default message for " << (DWORD)hrCode);
  439. wsprintf(szBuffer, (LPCTSTR)strMsg, hrCode);
  440. }
  441. else
  442. {
  443. //
  444. // Not enough room for message code
  445. //
  446. TRACEEOLID("Buffer too small for default message -- left blank");
  447. ASSERT(FALSE);
  448. *szBuffer = _T('\0');
  449. }
  450. }
  451. return hrReturn;
  452. }
  453. /* static */
  454. HRESULT
  455. CError::TextFromHRESULT(
  456. IN HRESULT hrCode,
  457. OUT CString & strBuffer
  458. )
  459. /*++
  460. Routine Description:
  461. Similar to the function above, but use a CString
  462. Arguments:
  463. HRESULT hrCode HRESULT or (DWORD WIN32 error) whose message to get
  464. CString & strBuffer Buffer to load message text into
  465. Return Value:
  466. HRESULT error code depending on whether the message was
  467. found. If the message was not found, some generic message
  468. is synthesized in the buffer if a buffer is provided.
  469. ERROR_FILE_NOT_FOUND No message found
  470. --*/
  471. {
  472. DWORD cchBuffer = 255;
  473. HRESULT hr = S_OK;
  474. for (;;)
  475. {
  476. LPTSTR szBuffer = strBuffer.GetBuffer(cchBuffer + 1);
  477. if (szBuffer == NULL)
  478. {
  479. return HResult(ERROR_NOT_ENOUGH_MEMORY);
  480. }
  481. hr = TextFromHRESULT(hrCode, szBuffer, cchBuffer);
  482. if (Win32Error(hr) != ERROR_INSUFFICIENT_BUFFER)
  483. {
  484. //
  485. // Done!
  486. //
  487. break;
  488. }
  489. //
  490. // Insufficient buffer, enlarge and try again
  491. //
  492. cchBuffer *= 2;
  493. }
  494. strBuffer.ReleaseBuffer();
  495. return hr;
  496. }
  497. /* static */
  498. BOOL
  499. CError::ExpandEscapeCode(
  500. IN LPTSTR szBuffer,
  501. IN DWORD cchBuffer,
  502. OUT IN LPTSTR & lp,
  503. IN CString & strReplacement,
  504. OUT HRESULT & hr
  505. )
  506. /*++
  507. Routine Description:
  508. Expand escape code
  509. Arguments:
  510. LPTSTR szBuffer Buffer
  511. DWORD cchBuffer Size of buffer
  512. LPTSTR & lp Pointer to escape code
  513. CString & strReplacement Message to replace the escape code
  514. HRESULT & hr Returns HRESULT in case of failure
  515. Return Value:
  516. TRUE if the replacement was successful, FALSE otherwise.
  517. In the case of failure, hr will return an HRESULT.
  518. In the case of success, lp will be advanced past the
  519. replacement string.
  520. --*/
  521. {
  522. //
  523. // Make sure there's room (account for terminating NULL)
  524. // Free up 2 spaces for the escape code.
  525. //
  526. int cchFmt = lstrlen(szBuffer) - 2;
  527. int cchReplacement = strReplacement.GetLength();
  528. int cchRemainder = lstrlen(lp + 2);
  529. if ((DWORD)(cchReplacement + cchFmt) < cchBuffer)
  530. {
  531. //
  532. // Put it in
  533. //
  534. MoveMemory(
  535. lp + cchReplacement,
  536. lp + 2,
  537. (cchRemainder + 1) * sizeof(TCHAR)
  538. );
  539. CopyMemory(lp, strReplacement, cchReplacement * sizeof(TCHAR));
  540. lp += cchReplacement;
  541. return TRUE;
  542. }
  543. hr = HResult(ERROR_INSUFFICIENT_BUFFER);
  544. return FALSE;
  545. }
  546. /* static */
  547. LPCTSTR
  548. CError::TextFromHRESULTExpand(
  549. IN HRESULT hrCode,
  550. OUT LPTSTR szBuffer,
  551. OUT DWORD cchBuffer,
  552. OUT HRESULT * phResult OPTIONAL
  553. )
  554. /*++
  555. Routine Description:
  556. Expand %h/%H strings in szBuffer to text from HRESULT,
  557. or error code respectively within the limits of szBuffer.
  558. Arguments:
  559. HRESULT hrCode HRESULT or (DWORD WIN32 error) whose message to get
  560. LPTSTR szBuffer Buffer to load message text into
  561. DWORD cchBuffer Buffer size in characters
  562. HRESULT * phResult Optional return code
  563. Return Value:
  564. Pointer to string.
  565. --*/
  566. {
  567. HRESULT hr = S_OK;
  568. if (szBuffer == NULL || cchBuffer <= 0)
  569. {
  570. hr = HResult(ERROR_INSUFFICIENT_BUFFER);
  571. }
  572. else
  573. {
  574. //
  575. // Look for the escape sequence
  576. //
  577. int cReplacements = 0;
  578. CString strMessage;
  579. LPTSTR lp = szBuffer;
  580. while (*lp)
  581. {
  582. if (*lp == s_chEscape)
  583. {
  584. switch(*(lp + 1))
  585. {
  586. case s_chEscText:
  587. //
  588. // Replace escape code with text message
  589. //
  590. hr = TextFromHRESULT(hrCode, strMessage);
  591. if (ExpandEscapeCode(
  592. szBuffer,
  593. cchBuffer,
  594. lp,
  595. strMessage,
  596. hr
  597. ))
  598. {
  599. ++cReplacements;
  600. }
  601. break;
  602. case s_chEscNumber:
  603. //
  604. // Replace escape code with numeric error code
  605. //
  606. strMessage.Format(_T("0x%08x"), hrCode);
  607. if (ExpandEscapeCode(
  608. szBuffer,
  609. cchBuffer,
  610. lp,
  611. strMessage,
  612. hr
  613. ))
  614. {
  615. ++cReplacements;
  616. }
  617. break;
  618. default:
  619. //
  620. // Regular printf-style escape sequence.
  621. //
  622. break;
  623. }
  624. }
  625. ++lp;
  626. }
  627. if (!cReplacements)
  628. {
  629. //
  630. // Got to the end without finding any escape codes.
  631. //
  632. hr = HResult(ERROR_INVALID_PARAMETER);
  633. }
  634. }
  635. if (phResult)
  636. {
  637. *phResult = hr;
  638. }
  639. return szBuffer;
  640. }
  641. /* static */
  642. LPCTSTR
  643. CError::TextFromHRESULTExpand(
  644. IN HRESULT hrCode,
  645. OUT CString & strBuffer
  646. )
  647. /*++
  648. Routine Description:
  649. Expand %h string in strBuffer to text from HRESULT
  650. Arguments:
  651. HRESULT hrCode HRESULT or (DWORD WIN32 error) whose message to get
  652. CString & strBuffer Buffer to load message text into
  653. Return Value:
  654. Pointer to string.
  655. --*/
  656. {
  657. DWORD cchBuffer = strBuffer.GetLength() + 1024;
  658. for (;;)
  659. {
  660. LPTSTR szBuffer = strBuffer.GetBuffer(cchBuffer + 1);
  661. if (szBuffer != NULL)
  662. {
  663. HRESULT hr;
  664. TextFromHRESULTExpand(hrCode, szBuffer, cchBuffer, &hr);
  665. if (Win32Error(hr) != ERROR_INSUFFICIENT_BUFFER)
  666. {
  667. //
  668. // Done!
  669. //
  670. break;
  671. }
  672. //
  673. // Insufficient buffer, enlarge and try again
  674. //
  675. cchBuffer *= 2;
  676. }
  677. }
  678. strBuffer.ReleaseBuffer();
  679. return strBuffer;
  680. }
  681. /* static */
  682. int
  683. CError::MessageBox(
  684. IN HRESULT hrCode,
  685. IN UINT nType,
  686. IN UINT nHelpContext OPTIONAL
  687. )
  688. /*++
  689. Routine Description:
  690. Display error message in a message box
  691. Arguments:
  692. HRESULT hrCode : HRESULT error code
  693. UINT nType : See AfxMessageBox for documentation
  694. UINT nHelpContext : See AfxMessageBox for documentation
  695. Return Value:
  696. AfxMessageBox return code
  697. --*/
  698. {
  699. CString strMsg;
  700. TextFromHRESULT(hrCode, strMsg);
  701. //
  702. // Ensure we have a CWinApp
  703. //
  704. if (AfxGetApp() != NULL)
  705. {
  706. return ::AfxMessageBox(strMsg, nType, nHelpContext);
  707. }
  708. //
  709. // Else hang the message box off the desktop.
  710. // this must be a console app
  711. //
  712. #ifndef _CONSOLE
  713. TRACEEOLID("No winapp detected -- using desktop as parent handle");
  714. ASSERT(FALSE);
  715. #endif // _CONSOLE
  716. return ::MessageBox(NULL, strMsg, NULL, nType);
  717. }
  718. //
  719. // Extend CString just to get at FormatV publically
  720. //
  721. class CStringEx : public CString
  722. {
  723. public:
  724. void FormatV(LPCTSTR lpszFormat, va_list argList)
  725. {
  726. CString::FormatV(lpszFormat, argList);
  727. }
  728. };
  729. int
  730. CError::MessageBoxFormat(
  731. IN UINT nFmt,
  732. IN UINT nType,
  733. IN UINT nHelpContext,
  734. ...
  735. ) const
  736. /*++
  737. Routine Description:
  738. Display formatted error message in messagebox. The format
  739. string (given as a resource ID) is a normal printf-style
  740. string, with the additional parameter of %h, which takes
  741. the text equivalent of the error message, or %H, which takes
  742. the error return code itself.
  743. Arguments:
  744. UINT nFmt : Resource format
  745. UINT nType : See AfxMessageBox for documentation
  746. UINT nHelpContext : See AfxMessageBox for documentation
  747. ... More as needed for sprintf
  748. Return Value:
  749. AfxMessageBox return code
  750. --*/
  751. {
  752. CString strFmt;
  753. CStringEx strMsg;
  754. strFmt.LoadString(nFmt);
  755. //
  756. // First expand the error
  757. //
  758. TextFromHRESULTExpand(m_hrCode, strFmt);
  759. va_list marker;
  760. va_start(marker, nHelpContext);
  761. strMsg.FormatV(strFmt, marker);
  762. va_end(marker);
  763. //
  764. // Ensure we have a CWinApp
  765. //
  766. if (AfxGetApp() != NULL)
  767. {
  768. return ::AfxMessageBox(strMsg, nType, nHelpContext);
  769. }
  770. //
  771. // Else hang the message box off the desktop.
  772. // this must be a console app
  773. //
  774. #ifndef _CONSOLE
  775. TRACEEOLID("No winapp detected -- using desktop as parent handle");
  776. ASSERT(FALSE);
  777. #endif // _CONSOLE
  778. return ::MessageBox(NULL, strMsg, NULL, nType);
  779. }
  780. BOOL
  781. CError::MessageBoxOnFailure(
  782. IN UINT nType,
  783. IN UINT nHelpContext OPTIONAL
  784. ) const
  785. /*++
  786. Routine Description:
  787. Display message box if the current error is a failure
  788. condition, else do nothing
  789. Arguments:
  790. UINT nType : See AfxMessageBox for documentation
  791. UINT nHelpContext : See AfxMessageBox for documentation
  792. Return Value:
  793. TRUE if a messagebox was shown, FALSE otherwise
  794. --*/
  795. {
  796. if (Failed())
  797. {
  798. MessageBox(nType, nHelpContext);
  799. return TRUE;
  800. }
  801. return FALSE;
  802. }
  803. /* static */
  804. BOOL
  805. CError::HasOverride(
  806. IN HRESULT hrCode,
  807. OUT UINT * pnMessage OPTIONAL
  808. )
  809. /*++
  810. Routine Description:
  811. Check to see if a given HRESULT has an override
  812. Arguments:
  813. HRESULT hrCode : HRESULT to check for
  814. UINT * pnMessage : Optionally returns the override
  815. Return Value:
  816. TRUE if there is an override, FALSE if there is not.
  817. --*/
  818. {
  819. RaiseThreadProtection();
  820. ASSERT(AreStaticsAllocated());
  821. UINT nID;
  822. hrCode = CvtToInternalFormat(hrCode);
  823. BOOL fResult = s_pmapOverrides->Lookup(hrCode, nID);
  824. if (fResult && pnMessage != NULL)
  825. {
  826. *pnMessage = nID;
  827. }
  828. LowerThreadProtection();
  829. return fResult;
  830. }
  831. /* static */
  832. UINT
  833. CError::AddOverride(
  834. IN HRESULT hrCode,
  835. IN UINT nMessage
  836. )
  837. /*++
  838. Routine Description:
  839. Add an override for a specific HRESULT.
  840. Arguments:
  841. HRESULT hrCode : HRESULT to override
  842. UINT nMessage : New message, or -1 to remove override
  843. Return Value:
  844. The previous override, or -1
  845. --*/
  846. {
  847. RaiseThreadProtection();
  848. ASSERT(AreStaticsAllocated());
  849. UINT nPrev;
  850. hrCode = CvtToInternalFormat(hrCode);
  851. //
  852. // Fetch the current override
  853. //
  854. if (!s_pmapOverrides->Lookup(hrCode, nPrev))
  855. {
  856. //
  857. // Didn't exist
  858. //
  859. nPrev = REMOVE_OVERRIDE;
  860. }
  861. if (nMessage == REMOVE_OVERRIDE)
  862. {
  863. //
  864. // Remove the override
  865. //
  866. s_pmapOverrides->RemoveKey(hrCode);
  867. }
  868. else
  869. {
  870. //
  871. // Set new override
  872. //
  873. s_pmapOverrides->SetAt(hrCode, nMessage);
  874. }
  875. LowerThreadProtection();
  876. return nPrev;
  877. }
  878. /* static */
  879. void
  880. CError::RemoveAllOverrides()
  881. /*++
  882. Routine Description:
  883. Remove all overrides
  884. Arguments:
  885. None
  886. Return Value:
  887. None
  888. --*/
  889. {
  890. RaiseThreadProtection();
  891. ASSERT(AreStaticsAllocated());
  892. s_pmapOverrides->RemoveAll();
  893. LowerThreadProtection();
  894. }
  895. /* static */
  896. LPCTSTR
  897. CError::FindFacility(
  898. IN DWORD dwFacility
  899. )
  900. /*++
  901. Routine Description:
  902. Determine if a DLL name has been registered for the given facility
  903. code.
  904. Arguments:
  905. DWORD dwFacility : Facility code
  906. Return Value:
  907. Returns the DLL name, or NULL.
  908. --*/
  909. {
  910. RaiseThreadProtection();
  911. ASSERT(AreStaticsAllocated());
  912. LPCTSTR pRes = NULL;
  913. CString strDLL;
  914. if (s_pmapFacilities->Lookup(dwFacility, strDLL))
  915. {
  916. pRes = strDLL;
  917. }
  918. LowerThreadProtection();
  919. return pRes;
  920. }
  921. /* static */
  922. void
  923. CError::RegisterFacility(
  924. IN DWORD dwFacility,
  925. IN LPCSTR lpDLL OPTIONAL
  926. )
  927. /*++
  928. Routine Description:
  929. Register a DLL for a given facility code. Use NULL to unregister
  930. the DLL name.
  931. Arguments:
  932. DWORD dwFacility : Facility code
  933. LPCSTR lpDLL : DLL Name.
  934. Return Value:
  935. None
  936. --*/
  937. {
  938. RaiseThreadProtection();
  939. ASSERT(AreStaticsAllocated());
  940. if (lpDLL == NULL)
  941. {
  942. //
  943. // Remove the facility
  944. //
  945. s_pmapFacilities->RemoveKey(dwFacility);
  946. }
  947. else
  948. {
  949. CString str(lpDLL);
  950. //
  951. // Register facility
  952. //
  953. s_pmapFacilities->SetAt(dwFacility, str);
  954. }
  955. LowerThreadProtection();
  956. }
  957. CError::~CError()
  958. /*++
  959. Routine Description:
  960. Destructor
  961. Arguments:
  962. None
  963. Return Value:
  964. N/A
  965. --*/
  966. {
  967. SAFE_DELETE(m_pstrBuff);
  968. }
  969. const CError &
  970. CError::Construct(
  971. IN HRESULT hr
  972. )
  973. /*++
  974. Routine Description:
  975. construct with new value.
  976. Arguments:
  977. HRESULT hr : New value, either an HRESULT or a WIN32
  978. error code.
  979. Return Value:
  980. Reference to current object
  981. --*/
  982. {
  983. ASSERT(AreStaticsAllocated());
  984. m_hrCode = CvtToInternalFormat(hr);
  985. SAFE_DELETE(m_pstrBuff);
  986. return *this;
  987. }
  988. const CError &
  989. CError::Construct(
  990. IN const CError & err
  991. )
  992. /*++
  993. Routine Description:
  994. Assign new value.
  995. Arguments:
  996. CError & err : Error code
  997. Return Value:
  998. Reference to current object
  999. --*/
  1000. {
  1001. ASSERT(AreStaticsAllocated());
  1002. m_hrCode = err.m_hrCode;
  1003. SAFE_DELETE(m_pstrBuff);
  1004. return *this;
  1005. }
  1006. CError::operator LPCTSTR()
  1007. /*++
  1008. Routine Description:
  1009. Convert message to text in internal buffer, and return
  1010. pointer to the internal buffer.
  1011. Arguments:
  1012. None
  1013. Return Value:
  1014. Pointer to internal buffer.
  1015. --*/
  1016. {
  1017. ASSERT(AreStaticsAllocated());
  1018. if (m_pstrBuff == NULL)
  1019. {
  1020. m_pstrBuff = new CString;
  1021. }
  1022. if (m_pstrBuff)
  1023. {
  1024. TextFromHRESULT(m_hrCode, *m_pstrBuff);
  1025. return (LPCTSTR)*m_pstrBuff;
  1026. }
  1027. return g_cszNull;
  1028. }
  1029. //
  1030. // Text dialog that warns of clear text violation
  1031. //
  1032. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1033. CClearTxtDlg::CClearTxtDlg(
  1034. IN CWnd * pParent OPTIONAL
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. Clear text dialog constructor
  1039. Arguments:
  1040. CWnd * pParent : Optional parent window
  1041. Return Value:
  1042. N/A
  1043. --*/
  1044. : CDialog(CClearTxtDlg::IDD, pParent)
  1045. {
  1046. //{{AFX_DATA_INIT(CClearTxtDlg)
  1047. //}}AFX_DATA_INIT
  1048. }
  1049. void
  1050. CClearTxtDlg::DoDataExchange(
  1051. IN CDataExchange * pDX
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. Initialise/Store control data
  1056. Arguments:
  1057. CDataExchange * pDX - DDX/DDV control structure
  1058. Return Value:
  1059. None
  1060. --*/
  1061. {
  1062. CDialog::DoDataExchange(pDX);
  1063. //{{AFX_DATA_MAP(CClearTxtDlg)
  1064. //}}AFX_DATA_MAP
  1065. }
  1066. //
  1067. // Message Map
  1068. //
  1069. BEGIN_MESSAGE_MAP(CClearTxtDlg, CDialog)
  1070. //{{AFX_MSG_MAP(CClearTxtDlg)
  1071. //}}AFX_MSG_MAP
  1072. END_MESSAGE_MAP()
  1073. //
  1074. // Message Handlers
  1075. //
  1076. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1077. BOOL
  1078. CClearTxtDlg::OnInitDialog()
  1079. /*++
  1080. Routine Description:
  1081. WM_INITDIALOG handler. Initialize the dialog.
  1082. Arguments:
  1083. None.
  1084. Return Value:
  1085. TRUE if no focus is to be set automatically, FALSE if the focus
  1086. is already set.
  1087. --*/
  1088. {
  1089. CDialog::OnInitDialog();
  1090. (GetDlgItem(IDCANCEL))->SetFocus();
  1091. CenterWindow();
  1092. MessageBeep(MB_ICONEXCLAMATION);
  1093. return FALSE;
  1094. }