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.

544 lines
14 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ExcOper.cpp
  7. //
  8. // Abstract:
  9. // Implementation of exception classes.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 20, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. // stdafx.h, TraceTag.h, and resource.h are all pulled from the project
  18. // directory.
  19. //
  20. // stdafx.h must have an IDS typedef and disable some W4 warnings.
  21. //
  22. // TraceTag.h must define TraceError.
  23. //
  24. // resource.h must define IDS_UNKNOWN_ERROR, and the string must be
  25. // defined something like "Error %d (0x%08.8x)." in the resource file.
  26. //
  27. /////////////////////////////////////////////////////////////////////////////
  28. #include <string.h>
  29. #include "ExcOper.h"
  30. #include "TraceTag.h"
  31. #include "resource.h"
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CExceptionWithOper
  39. /////////////////////////////////////////////////////////////////////////////
  40. IMPLEMENT_DYNAMIC(CExceptionWithOper, CException)
  41. /////////////////////////////////////////////////////////////////////////////
  42. //++
  43. //
  44. // CExceptionWithOper::CExceptionWithOper
  45. //
  46. // Routine Description:
  47. // Constructor.
  48. //
  49. // Arguments:
  50. // idsOperation [IN] String ID for operation occurring during exception.
  51. // pszOperArg1 [IN] 1st argument to operation string.
  52. // pszOperArg2 [IN] 2nd argument to operation string.
  53. //
  54. // Return Value:
  55. // None.
  56. //
  57. //--
  58. /////////////////////////////////////////////////////////////////////////////
  59. CExceptionWithOper::CExceptionWithOper(
  60. IN IDS idsOperation,
  61. IN LPCTSTR pszOperArg1,
  62. IN LPCTSTR pszOperArg2
  63. )
  64. {
  65. SetOperation(idsOperation, pszOperArg1, pszOperArg2);
  66. } //*** CExceptionWithOper::CExceptionWithOper()
  67. /////////////////////////////////////////////////////////////////////////////
  68. //++
  69. //
  70. // CExceptionWithOper::CExceptionWithOper
  71. //
  72. // Routine Description:
  73. // Constructor.
  74. //
  75. // Arguments:
  76. // idsOperation [IN] String ID for operation occurring during exception.
  77. // pszOperArg1 [IN] 1st argument to operation string.
  78. // pszOperArg2 [IN] 2nd argument to operation string.
  79. // bAutoDelete [IN] Auto-delete the exception in Delete().
  80. //
  81. // Return Value:
  82. // None.
  83. //
  84. //--
  85. /////////////////////////////////////////////////////////////////////////////
  86. CExceptionWithOper::CExceptionWithOper(
  87. IN IDS idsOperation,
  88. IN LPCTSTR pszOperArg1,
  89. IN LPCTSTR pszOperArg2,
  90. IN BOOL bAutoDelete
  91. ) : CException(bAutoDelete)
  92. {
  93. SetOperation(idsOperation, pszOperArg1, pszOperArg2);
  94. } //*** CExceptionWithOper::CExceptionWithOper()
  95. /////////////////////////////////////////////////////////////////////////////
  96. //++
  97. //
  98. // CExceptionWithOper::~CExceptionWithOper
  99. //
  100. // Routine Description:
  101. // Destructor.
  102. //
  103. // Arguments:
  104. // None.
  105. //
  106. // Return Value:
  107. // None.
  108. //
  109. //--
  110. /////////////////////////////////////////////////////////////////////////////
  111. CExceptionWithOper::~CExceptionWithOper(void)
  112. {
  113. } //*** CExceptionWithOper::~CExceptionWithOper()
  114. /////////////////////////////////////////////////////////////////////////////
  115. //++
  116. //
  117. // CExceptionWithOper::GetErrorMessage
  118. //
  119. // Routine Description:
  120. // Get the error message represented by the exception.
  121. //
  122. // Arguments:
  123. // lpszError [OUT] String in which to return the error message.
  124. // nMaxError [IN] Maximum length of the output string.
  125. // pnHelpContext [OUT] Help context for the error message.
  126. //
  127. // Return Value:
  128. // None.
  129. //
  130. //--
  131. /////////////////////////////////////////////////////////////////////////////
  132. BOOL CExceptionWithOper::GetErrorMessage(
  133. LPTSTR lpszError,
  134. UINT nMaxError,
  135. PUINT pnHelpContext
  136. )
  137. {
  138. // Format the operation string.
  139. FormatWithOperation(lpszError, nMaxError, NULL);
  140. return TRUE;
  141. } //*** CExceptionWithOper::GetErrorMessage()
  142. /////////////////////////////////////////////////////////////////////////////
  143. //++
  144. //
  145. // CExceptionWithOper::ReportError
  146. //
  147. // Routine Description:
  148. // Report an error from the exception. Overriding to get a bigger
  149. // error message buffer.
  150. //
  151. // Arguments:
  152. // nType [IN] Type of message box.
  153. // nError [IN] ID of a mesage to display if exception has no message.
  154. //
  155. // Return Value:
  156. // None.
  157. //
  158. //--
  159. /////////////////////////////////////////////////////////////////////////////
  160. int CExceptionWithOper::ReportError(
  161. UINT nType /* = MB_OK */,
  162. UINT nError /* = 0 */
  163. )
  164. {
  165. TCHAR szErrorMessage[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
  166. int nDisposition;
  167. UINT nHelpContext;
  168. if (GetErrorMessage(szErrorMessage, sizeof(szErrorMessage) / sizeof(TCHAR), &nHelpContext))
  169. nDisposition = AfxMessageBox(szErrorMessage, nType, nHelpContext);
  170. else
  171. {
  172. if (nError == 0)
  173. nError = AFX_IDP_NO_ERROR_AVAILABLE;
  174. nDisposition = AfxMessageBox(nError, nType, nHelpContext);
  175. }
  176. return nDisposition;
  177. } //*** CExceptionWithOper::ReportError()
  178. /////////////////////////////////////////////////////////////////////////////
  179. //++
  180. //
  181. // CExceptionWithOper::SetOperation
  182. //
  183. // Routine Description:
  184. // Constructor.
  185. //
  186. // Arguments:
  187. // idsOperation [IN] String ID for operation occurring during exception.
  188. // pszOperArg1 [IN] 1st argument to operation string.
  189. // pszOperArg2 [IN] 2nd argument to operation string.
  190. //
  191. // Return Value:
  192. // None.
  193. //
  194. //--
  195. /////////////////////////////////////////////////////////////////////////////
  196. void CExceptionWithOper::SetOperation(
  197. IN IDS idsOperation,
  198. IN LPCTSTR pszOperArg1,
  199. IN LPCTSTR pszOperArg2
  200. )
  201. {
  202. m_idsOperation = idsOperation;
  203. if (pszOperArg1 == NULL)
  204. m_szOperArg1[0] = _T('\0');
  205. else
  206. {
  207. ::_tcsncpy(m_szOperArg1, pszOperArg1, (sizeof(m_szOperArg1) / sizeof(TCHAR)) - 1);
  208. m_szOperArg1[(sizeof(m_szOperArg1) / sizeof(TCHAR))- 1] = _T('\0');
  209. } // else: first argument specified
  210. if (pszOperArg2 == NULL)
  211. m_szOperArg2[0] = _T('\0');
  212. else
  213. {
  214. ::_tcsncpy(m_szOperArg2, pszOperArg2, (sizeof(m_szOperArg2) / sizeof(TCHAR)) - 1);
  215. m_szOperArg2[(sizeof(m_szOperArg2) / sizeof(TCHAR)) - 1] = _T('\0');
  216. } // else: second argument specified
  217. } //*** CExceptionWithOper::SetOperation()
  218. /////////////////////////////////////////////////////////////////////////////
  219. //++
  220. //
  221. // CExceptionWithOper::FormatWithOperation
  222. //
  223. // Routine Description:
  224. // Get the error message represented by the exception.
  225. //
  226. // Arguments:
  227. // lpszError [OUT] String in which to return the error message.
  228. // nMaxError [IN] Maximum length of the output string.
  229. // pszMsg [IN] Message to format with the operation string.
  230. //
  231. // Return Value:
  232. // None.
  233. //
  234. //--
  235. /////////////////////////////////////////////////////////////////////////////
  236. void CExceptionWithOper::FormatWithOperation(
  237. OUT LPTSTR lpszError,
  238. IN UINT nMaxError,
  239. IN LPCTSTR pszMsg
  240. )
  241. {
  242. DWORD dwResult;
  243. TCHAR szOperation[EXCEPT_MAX_OPER_ARG_LENGTH];
  244. TCHAR szFmtOperation[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
  245. ASSERT(lpszError != NULL);
  246. ASSERT(nMaxError > 0);
  247. // Format the operation string.
  248. if (m_idsOperation)
  249. {
  250. void * rgpvArgs[2] = { m_szOperArg1, m_szOperArg2 };
  251. // Load the operation string.
  252. dwResult = ::LoadString(AfxGetApp()->m_hInstance, m_idsOperation, szOperation, (sizeof(szOperation) / sizeof(TCHAR)));
  253. ASSERT(dwResult != 0);
  254. // Format the operation string.
  255. ::FormatMessage(
  256. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  257. szOperation,
  258. 0,
  259. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  260. szFmtOperation,
  261. sizeof(szFmtOperation) / sizeof(TCHAR),
  262. (va_list *) rgpvArgs
  263. );
  264. // ::_sntprintf(szFmtOperation, (sizeof(szFmtOperation) / sizeof(TCHAR)) - 1, szOperation, m_szOperArg1, m_szOperArg2);
  265. szFmtOperation[(sizeof(szFmtOperation) / sizeof(TCHAR)) - 1] = _T('\0');
  266. // Format the final error message.
  267. if (pszMsg != NULL)
  268. ::_sntprintf(lpszError, nMaxError - 1, _T("%s\n\n%s"), szFmtOperation, pszMsg);
  269. else
  270. ::_tcsncpy(lpszError, szFmtOperation, nMaxError - 1);
  271. lpszError[nMaxError - 1] = _T('\0');
  272. } // if: operation string specified
  273. else
  274. {
  275. if (pszMsg != NULL)
  276. {
  277. ::_tcsncpy(lpszError, pszMsg, nMaxError - 1);
  278. lpszError[nMaxError - 1] = _T('\0');
  279. } // if: additional message specified
  280. else
  281. lpszError[0] = _T('\0');
  282. } // else: no operation string specified
  283. } //*** CExceptionWithOper::FormatWithOperation()
  284. //***************************************************************************
  285. /////////////////////////////////////////////////////////////////////////////
  286. // CException
  287. /////////////////////////////////////////////////////////////////////////////
  288. IMPLEMENT_DYNAMIC(CNTException, CExceptionWithOper)
  289. /////////////////////////////////////////////////////////////////////////////
  290. //++
  291. //
  292. // CNTException::CNTException
  293. //
  294. // Routine Description:
  295. // Constructor.
  296. //
  297. // Arguments:
  298. // sc [IN] NT status code.
  299. // idsOperation [IN] String ID for operation occurring during exception.
  300. // pszOperArg1 [IN] 1st argument to operation string.
  301. // pszOperArg2 [IN] 2nd argument to operation string.
  302. //
  303. // Return Value:
  304. // None.
  305. //
  306. //--
  307. /////////////////////////////////////////////////////////////////////////////
  308. CNTException::CNTException(
  309. IN SC sc,
  310. IN IDS idsOperation,
  311. IN LPCTSTR pszOperArg1,
  312. IN LPCTSTR pszOperArg2
  313. ) : CExceptionWithOper(idsOperation, pszOperArg1, pszOperArg2)
  314. {
  315. m_sc = sc;
  316. } //*** CNTException::CNTException()
  317. /////////////////////////////////////////////////////////////////////////////
  318. //++
  319. //
  320. // CNTException::CNTException
  321. //
  322. // Routine Description:
  323. // Constructor.
  324. //
  325. // Arguments:
  326. // sc [IN] NT status code.
  327. // idsOperation [IN] String ID for operation occurring during exception.
  328. // pszOperArg1 [IN] 1st argument to operation string.
  329. // pszOperArg2 [IN] 2nd argument to operation string.
  330. // bAutoDelete [IN] Auto-delete the exception in Delete().
  331. //
  332. // Return Value:
  333. // None.
  334. //
  335. //--
  336. /////////////////////////////////////////////////////////////////////////////
  337. CNTException::CNTException(
  338. IN SC sc,
  339. IN IDS idsOperation,
  340. IN LPCTSTR pszOperArg1,
  341. IN LPCTSTR pszOperArg2,
  342. IN BOOL bAutoDelete
  343. ) : CExceptionWithOper(idsOperation, pszOperArg1, pszOperArg2, bAutoDelete)
  344. {
  345. m_sc = sc;
  346. } //*** CNTException::CNTException()
  347. /////////////////////////////////////////////////////////////////////////////
  348. //++
  349. //
  350. // CNTException::~CNTException
  351. //
  352. // Routine Description:
  353. // Destructor.
  354. //
  355. // Arguments:
  356. // None.
  357. //
  358. // Return Value:
  359. // None.
  360. //
  361. //--
  362. /////////////////////////////////////////////////////////////////////////////
  363. CNTException::~CNTException(void)
  364. {
  365. } //*** CNTException::~CNTException()
  366. /////////////////////////////////////////////////////////////////////////////
  367. //++
  368. //
  369. // CNTException::GetErrorMessage
  370. //
  371. // Routine Description:
  372. // Get the error message represented by the exception.
  373. //
  374. // Arguments:
  375. // lpszError [OUT] String in which to return the error message.
  376. // nMaxError [IN] Maximum length of the output string.
  377. // pnHelpContext [OUT] Help context for the error message.
  378. //
  379. // Return Value:
  380. // TRUE Message available.
  381. // FALSE No message available.
  382. //
  383. //--
  384. /////////////////////////////////////////////////////////////////////////////
  385. BOOL CNTException::GetErrorMessage(
  386. LPTSTR lpszError,
  387. UINT nMaxError,
  388. PUINT pnHelpContext
  389. )
  390. {
  391. DWORD dwResult;
  392. TCHAR szNtMsg[128];
  393. // Format the NT status code from the system.
  394. dwResult = ::FormatMessage(
  395. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  396. NULL,
  397. m_sc,
  398. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  399. szNtMsg,
  400. sizeof(szNtMsg) / sizeof(TCHAR),
  401. 0
  402. );
  403. if (dwResult == 0)
  404. {
  405. // Format the NT status code from NTDLL since this hasn't been
  406. // integrated into the system yet.
  407. dwResult = ::FormatMessage(
  408. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
  409. ::GetModuleHandle(_T("NTDLL.DLL")),
  410. m_sc,
  411. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  412. szNtMsg,
  413. sizeof(szNtMsg) / sizeof(TCHAR),
  414. 0
  415. );
  416. if (dwResult == 0)
  417. {
  418. TCHAR szErrorFmt[EXCEPT_MAX_OPER_ARG_LENGTH];
  419. dwResult = ::LoadString(AfxGetApp()->m_hInstance, IDS_UNKNOWN_ERROR, szErrorFmt, (sizeof(szErrorFmt) / sizeof(TCHAR)));
  420. ASSERT(dwResult != 0);
  421. ::_sntprintf(szNtMsg, sizeof(szNtMsg) / sizeof(TCHAR), szErrorFmt, m_sc, m_sc);
  422. } // if: error formatting status code from NTDLL
  423. } // if: error formatting status code from system
  424. // Format the message with the operation string.
  425. FormatWithOperation(lpszError, nMaxError, szNtMsg);
  426. return TRUE;
  427. } //*** CNTException::GetErrorMessage()
  428. //***************************************************************************
  429. /////////////////////////////////////////////////////////////////////////////
  430. // Global Functions
  431. /////////////////////////////////////////////////////////////////////////////
  432. static CNTException gs_nte(ERROR_SUCCESS, NULL, NULL, NULL, FALSE);
  433. static CExceptionWithOper gs_ewo(NULL, NULL, NULL, FALSE);
  434. /////////////////////////////////////////////////////////////////////////////
  435. //++
  436. //
  437. // ThrowStaticException
  438. //
  439. // Purpose:
  440. // Throw the static NT Exception.
  441. //
  442. // Arguments:
  443. // sc [IN] NT status code.
  444. // idsOperation [IN] String ID for operation occurring during exception.
  445. // pszOperArg1 [IN] 1st argument to operation string.
  446. // pszOperArg2 [IN] 2nd argument to operation string.
  447. //
  448. // Returns:
  449. // None.
  450. //
  451. //--
  452. /////////////////////////////////////////////////////////////////////////////
  453. void ThrowStaticException(
  454. IN SC sc,
  455. IN IDS idsOperation,
  456. IN LPCTSTR pszOperArg1,
  457. IN LPCTSTR pszOperArg2
  458. )
  459. {
  460. gs_nte.SetOperation(sc, idsOperation, pszOperArg1, pszOperArg2);
  461. TraceError(gs_nte);
  462. throw &gs_nte;
  463. } //*** ThrowStaticException()
  464. /////////////////////////////////////////////////////////////////////////////
  465. //++
  466. //
  467. // ThrowStaticException
  468. //
  469. // Purpose:
  470. // Throw the static Cluster Administrator Exception.
  471. //
  472. // Arguments:
  473. // idsOperation [IN] String ID for operation occurring during exception.
  474. // pszOperArg1 [IN] 1st argument to operation string.
  475. // pszOperArg2 [IN] 2nd argument to operation string.
  476. //
  477. // Returns:
  478. // None.
  479. //
  480. //--
  481. /////////////////////////////////////////////////////////////////////////////
  482. void ThrowStaticException(
  483. IN IDS idsOperation,
  484. IN LPCTSTR pszOperArg1,
  485. IN LPCTSTR pszOperArg2
  486. )
  487. {
  488. gs_ewo.SetOperation(idsOperation, pszOperArg1, pszOperArg2);
  489. TraceError(gs_ewo);
  490. throw &gs_ewo;
  491. } //*** ThrowStaticException()