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. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: mmcerror.cpp
  7. //
  8. // Contents: Class definitions for mmc debug support code.
  9. //
  10. // History: 15-Jul-99 VivekJ Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include "conuistr.h" // needed for IDR_MAINFRAME
  15. #define cchMaxSmallLine 256
  16. #ifdef DBG
  17. CTraceTag tagSCConversion(TEXT("SC"), TEXT("Conversion"));
  18. CTraceTag tagCallDump( TEXT("Function calls"), TEXT("ALL") );
  19. #endif //DBG
  20. //############################################################################
  21. //############################################################################
  22. //
  23. // Definition of GetStringModule() - used by all binaries
  24. //
  25. //############################################################################
  26. //############################################################################
  27. HINSTANCE GetStringModule()
  28. {
  29. return SC::GetHinst();
  30. }
  31. //############################################################################
  32. //############################################################################
  33. //
  34. // Implementation of class SC
  35. //
  36. //############################################################################
  37. //############################################################################
  38. // static variables
  39. HINSTANCE SC::s_hInst = 0;
  40. HWND SC::s_hWnd = NULL;
  41. DWORD SC::s_dwMainThreadID = -1;
  42. #ifdef DBG
  43. UINT SC::s_CallDepth = 0;
  44. #endif
  45. // accessors for the static variables.
  46. void
  47. SC::SetHinst(HINSTANCE hInst)
  48. {
  49. s_hInst = hInst;
  50. }
  51. void
  52. SC::SetHWnd(HWND hWnd)
  53. {
  54. s_hWnd = hWnd;
  55. }
  56. void
  57. SC::SetMainThreadID(DWORD dwThreadID)
  58. {
  59. ASSERT(-1 != dwThreadID);
  60. s_dwMainThreadID = dwThreadID;
  61. }
  62. #ifdef DBG
  63. SC&
  64. SC::operator = (const SC& other)
  65. {
  66. m_facility = other.m_facility;
  67. m_value = other.m_value;
  68. return *this;
  69. }
  70. SC::SC(const SC& other)
  71. : m_szFunctionName(NULL),
  72. m_szSnapinName(NULL)
  73. {
  74. *this = other;
  75. }
  76. /*+-------------------------------------------------------------------------*
  77. *
  78. * SC::SetFunctionName
  79. *
  80. * PURPOSE: Sets the debug function name to the supplied string.
  81. *
  82. * PARAMETERS:
  83. * LPCTSTR szFunctionName : the supplied string.
  84. *
  85. * RETURNS:
  86. * inline void
  87. *
  88. *+-------------------------------------------------------------------------*/
  89. inline void SC::SetFunctionName(LPCTSTR szFunctionName)
  90. {
  91. m_szFunctionName = szFunctionName;
  92. INCREMENT_CALL_DEPTH();
  93. // This computes the format string based on the call depth.
  94. // eg if s_CallDepth is 4, the string is " %s" (four spaces)
  95. // if s_CallDepth is 5, the string is " %s" (five spaces)
  96. LPCTSTR szFormatString = TEXT(" %s");
  97. UINT maxLen = _tcslen(szFormatString);
  98. UINT formatLen = s_CallDepth + 2; // the -2 is for the "%s"
  99. formatLen = (formatLen < maxLen ? formatLen : maxLen);
  100. Trace(tagCallDump, szFormatString + (maxLen - formatLen), szFunctionName);
  101. }
  102. #endif
  103. /*+-------------------------------------------------------------------------*
  104. *
  105. * SC::ToHr
  106. *
  107. * PURPOSE: Converts from a status code (SC) to an HRESULT. USE SPARINGLY.
  108. *
  109. * PARAMETERS: None
  110. *
  111. * RETURNS:
  112. * HRESULT
  113. *
  114. *+-------------------------------------------------------------------------*/
  115. HRESULT
  116. SC::ToHr() const
  117. {
  118. HRESULT hr = S_OK;
  119. switch(GetFacility())
  120. {
  121. default:
  122. ASSERT(0 && "Should not come here.");
  123. break;
  124. case FACILITY_WIN:
  125. hr = HRESULT_FROM_WIN32 (GetCode());
  126. break;
  127. case FACILITY_MMC:
  128. Trace (tagSCConversion, _T("Converting from MMC error code to HRESULT, probable loss of fidelity"), *this);
  129. hr = (GetCode() != 0) ? E_UNEXPECTED : S_OK;
  130. break;
  131. case FACILITY_HRESULT:
  132. hr = (HRESULT) GetCode();
  133. break;
  134. }
  135. return hr;
  136. }
  137. /*+-------------------------------------------------------------------------*
  138. *
  139. * SC::GetErrorMessage
  140. *
  141. * PURPOSE: Writes the error message corresponding to the error code to
  142. * the buffer pointed to by szMessage.
  143. *
  144. * PARAMETERS:
  145. * UINT maxLength : The maximum no of characters to output.
  146. * LPTSTR szMessage : Pointer to the buffer to use. Must be non-null.
  147. *
  148. * RETURNS:
  149. * void
  150. *
  151. *+-------------------------------------------------------------------------*/
  152. void SC::GetErrorMessage(UINT maxLength, /*[OUT]*/ LPTSTR szMessage) const
  153. {
  154. ASSERT(szMessage != NULL && maxLength > 0);
  155. if (szMessage == NULL || maxLength == 0)
  156. return;
  157. szMessage[0] = 0;
  158. switch(GetFacility())
  159. {
  160. default:
  161. ASSERT(0 && "SC::GetErrorMessage: Unknown SC facility.");
  162. break;
  163. case FACILITY_WIN:
  164. case FACILITY_HRESULT:
  165. {
  166. int nChars = 0;
  167. if ( GetCode() == E_UNEXPECTED )
  168. {
  169. nChars = ::LoadString(SC::GetHinst(), IDS_E_UNEXPECTED, szMessage, maxLength);
  170. }
  171. else
  172. {
  173. DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
  174. void *lpSource = NULL;
  175. // add XML module to be searched as well
  176. HMODULE hmodXML = GetModuleHandle(_T("msxml.dll"));
  177. if (hmodXML)
  178. {
  179. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  180. lpSource = hmodXML;
  181. }
  182. DWORD dwMessageID = GetCode();
  183. // reverse values made by HRESULT_FROM_WIN32
  184. // Not sure why ::FormatMessage does not work with such values,
  185. // but we need to convert them back, or else there won't be any messages
  186. if ( (dwMessageID & 0xFFFF0000) == ((FACILITY_WIN32 << 16) | 0x80000000) )
  187. dwMessageID &= 0x0000FFFF;
  188. nChars = ::FormatMessage( dwFlags,
  189. lpSource,
  190. dwMessageID,
  191. 0, /*dwLangID*/
  192. szMessage, /*lpBuffer*/
  193. maxLength, /*nSize*/
  194. 0 /*Arguments*/
  195. );
  196. }
  197. if (nChars)
  198. break;
  199. // if former failed - add a default error
  200. nChars = ::LoadString(SC::GetHinst(), IDS_MESSAGE_NOT_FOUND_ERROR, szMessage, maxLength);
  201. if (nChars == 0)
  202. {
  203. // too bad. we can only use hardcoded one
  204. _tcsncpy(szMessage, _T("Unknown error"), maxLength);
  205. szMessage[maxLength - 1] = 0;
  206. }
  207. }
  208. break;
  209. case FACILITY_MMC:
  210. {
  211. int nChars = ::LoadString(GetHinst(), GetCode(), szMessage, maxLength);
  212. if(nChars == 0) // did not exist
  213. {
  214. nChars = ::LoadString(GetHinst(), IDS_MESSAGE_NOT_FOUND_ERROR, szMessage, maxLength);
  215. ASSERT(nChars > 0);
  216. }
  217. }
  218. break;
  219. }
  220. }
  221. /*+-------------------------------------------------------------------------*
  222. *
  223. * SC::GetHelpID
  224. *
  225. * PURPOSE: Returns the help ID associated with a status code
  226. *
  227. * RETURNS:
  228. * DWORD
  229. *
  230. *+-------------------------------------------------------------------------*/
  231. DWORD
  232. SC::GetHelpID()
  233. {
  234. return 0; // TODO
  235. }
  236. LPCTSTR
  237. SC::GetHelpFile()
  238. {
  239. static TCHAR szFilePath[MAX_PATH] = TEXT("\0");
  240. // set the path if not already set
  241. if(*szFilePath == TEXT('\0') )
  242. {
  243. DWORD dwCnt = ExpandEnvironmentStrings(_T("%WINDIR%\\help\\mmc.chm"), szFilePath, MAX_PATH);
  244. ASSERT(dwCnt != 0);
  245. }
  246. return szFilePath;
  247. }
  248. void SC::Throw() throw(SC)
  249. {
  250. // make exact copy of itself and destroy it (forces all the output)
  251. #ifdef DBG
  252. {
  253. SC sc(*this);
  254. sc.SetFunctionName(m_szFunctionName);
  255. // forget the debug info - it will not be usefull anyway
  256. // This will turn off the Trace on destructor
  257. SetFunctionName(NULL);
  258. }
  259. #endif // DBG
  260. throw(*this);
  261. }
  262. void SC::Throw(HRESULT hr)
  263. {
  264. (*this) = hr;
  265. Throw();
  266. }
  267. /*+-------------------------------------------------------------------------*
  268. *
  269. * SC::FatalError
  270. *
  271. * PURPOSE: Terminates the application.
  272. *
  273. * RETURNS:
  274. * void
  275. *
  276. *+-------------------------------------------------------------------------*/
  277. void
  278. SC::FatalError() const
  279. {
  280. MMCErrorBox(*this);
  281. exit(1);
  282. }
  283. /*+-------------------------------------------------------------------------*
  284. *
  285. * SC::FromLastError
  286. *
  287. * PURPOSE: Fill SC with value from GetLastError.
  288. *
  289. * The SC is guaranteed to contain a failure code (i.e. IsError()
  290. * will return true) when this function returns.
  291. *
  292. * RETURNS: Reference to the current SC
  293. *
  294. *+-------------------------------------------------------------------------*/
  295. SC& SC::FromLastError()
  296. {
  297. FromWin32 (::GetLastError());
  298. /*
  299. * Some APIs will fail without setting extended error information.
  300. * Presumably this function was called in response to an error, so
  301. * we always want this SC to indicate *some* sort of error. If the
  302. * failing API neglected to set extended error information, give
  303. * this SC a generic error code
  304. */
  305. if (!IsError())
  306. MakeSc (FACILITY_HRESULT, E_FAIL);
  307. ASSERT (IsError());
  308. return (*this);
  309. }
  310. //############################################################################
  311. //############################################################################
  312. //
  313. // Error formatting
  314. //
  315. //############################################################################
  316. //############################################################################
  317. /*
  318. * Purpose: Formats an error message
  319. *
  320. * Parameters:
  321. * ids String describing the operation in progress
  322. * sc Error code describing the problem encountered
  323. * pstrMessage
  324. * the resulting message.
  325. */
  326. void FormatErrorIds(UINT ids, SC sc, UINT maxLength, /*[OUT]*/ LPTSTR szMessage)
  327. {
  328. TCHAR sz[cchMaxSmallLine];
  329. LoadString(SC::GetHinst(), IDR_MAINFRAME, sz, cchMaxSmallLine);
  330. FormatErrorString(sz, sc, maxLength, szMessage);
  331. }
  332. //
  333. // Returns a short version of an error message associated a given SC.
  334. //
  335. void FormatErrorShort(SC sc, UINT maxLength, /*[OUT]*/ LPTSTR szMessage)
  336. {
  337. FormatErrorString(NULL, sc, maxLength, szMessage, TRUE);
  338. }
  339. //
  340. // FormatErrorString formats an error message from any SC
  341. //
  342. // Parameters:
  343. // szOperation
  344. // String describing the operation in progress
  345. // May be NULL if sc is sufficient.
  346. // szMessage
  347. // the resulting message.
  348. // fShort
  349. // TRUE if you want the error message only (no header/footer)
  350. //
  351. void FormatErrorString(LPCTSTR szOperation, SC sc , UINT maxLength, /*[OUT]*/ LPTSTR szMessage, BOOL fShort)
  352. {
  353. sc.GetErrorMessage(maxLength, szMessage);
  354. // TODO: add p
  355. }
  356. //############################################################################
  357. //############################################################################
  358. //
  359. // MMCErrorBox
  360. //
  361. //############################################################################
  362. //############################################################################
  363. /*
  364. * MMCErrorBox
  365. *
  366. * Purpose: Displays an Error Box for the given SZ.
  367. * NOTE: This is the one that actually puts-up the dialog.
  368. *
  369. * Parameters:
  370. * sz Pointer to the message to display
  371. * fuStyle As per windows MessageBox
  372. *
  373. * Return value:
  374. * int Button Pressed to dismiss the ErrorBox
  375. */
  376. int MMCErrorBox(LPCTSTR szMessage, UINT fuStyle )
  377. {
  378. INT id;
  379. // If not system modal (background thread), force task modal.
  380. if (!(fuStyle & MB_SYSTEMMODAL))
  381. fuStyle |= MB_TASKMODAL;
  382. TCHAR szCaption[cchMaxSmallLine];
  383. LoadString(SC::GetHinst(), IDR_MAINFRAME, szCaption, cchMaxSmallLine);
  384. // get window to parent the message box
  385. HWND hWndActive = SC::GetHWnd();
  386. // cannot parent on hidden window!
  387. if ( !IsWindowVisible(hWndActive) )
  388. hWndActive = NULL;
  389. id = ::MessageBox(hWndActive, szMessage, szCaption, fuStyle);
  390. return id;
  391. }
  392. /*+-------------------------------------------------------------------------*
  393. *
  394. * MMCErrorBox
  395. *
  396. * PURPOSE: Displays an error box with the specified message and style
  397. *
  398. * PARAMETERS:
  399. * UINT idsOperation :
  400. * UINT fuStyle :
  401. *
  402. * RETURNS:
  403. * int: Button pressed
  404. *
  405. *+-------------------------------------------------------------------------*/
  406. int
  407. MMCErrorBox(UINT idsOperation, UINT fuStyle)
  408. {
  409. TCHAR sz[cchMaxSmallLine];
  410. LoadString(SC::GetHinst(), idsOperation, sz, cchMaxSmallLine);
  411. return MMCErrorBox(sz, fuStyle);
  412. }
  413. /*
  414. * MMCErrorBox
  415. *
  416. * Purpose: Displays a complex Error Box, given the operation
  417. * and the status code
  418. *
  419. * Parameters:
  420. * ids description of the operation that failed.
  421. * SC Status Code to report
  422. * fuStyle As per windows MessageBox
  423. *
  424. * Return value:
  425. * int Button Pressed to dismiss the ErrorBox
  426. */
  427. int MMCErrorBox(UINT ids, SC sc, UINT fuStyle)
  428. {
  429. TCHAR sz[cchMaxSmallLine];
  430. LoadString(SC::GetHinst(), ids, sz, cchMaxSmallLine);
  431. return MMCErrorBox(sz, sc, fuStyle);
  432. }
  433. /*
  434. * MMCErrorBox
  435. *
  436. * Purpose: Displays a complex Error Box, given the operation
  437. * and the status code
  438. *
  439. * Parameters:
  440. * szOperation Description of the operation that failed.
  441. * sz Status Code to report
  442. * fuStyle As per windows MessageBox
  443. *
  444. * Return value:
  445. * int Button Pressed to dismiss the ErrorBox
  446. */
  447. int MMCErrorBox(LPCTSTR szOperation, SC sc, UINT fuStyle)
  448. {
  449. TCHAR sz[cchMaxSmallLine];
  450. FormatErrorString(szOperation, sc, cchMaxSmallLine, sz);
  451. return MMCErrorBox(sz, fuStyle);
  452. }
  453. /*
  454. * MMCErrorBox
  455. *
  456. * Purpose: Displays an Error Box for the given Status Code.
  457. *
  458. * Parameters:
  459. * SC Status Code to report
  460. * fuStyle As per windows MessageBox
  461. *
  462. * Return value:
  463. * int Button Pressed to dismiss the ErrorBox
  464. */
  465. int MMCErrorBox(SC sc, UINT fuStyle)
  466. {
  467. TCHAR sz[cchMaxSmallLine];
  468. FormatErrorString(NULL, sc, cchMaxSmallLine, sz);
  469. return MMCErrorBox(sz, fuStyle);
  470. }