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.

957 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: errutil.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "errutil.h"
  12. #include "mprapi.h"
  13. #include "mprerror.h"
  14. #include "raserror.h"
  15. #define IS_WIN32_HRESULT(x) (((x) & 0xFFFF0000) == 0x80070000)
  16. #define WIN32_FROM_HRESULT(hr) (0x0000FFFF & (hr))
  17. /*!--------------------------------------------------------------------------
  18. FormatError
  19. -
  20. Author: KennT
  21. ---------------------------------------------------------------------------*/
  22. TFSCORE_API(HRESULT) FormatError(HRESULT hr, TCHAR *pszBuffer, UINT cchBuffer)
  23. {
  24. DWORD dwErr;
  25. // Copy over default message into szBuffer
  26. _tcscpy(pszBuffer, _T("Error"));
  27. // Ok, we can't get the error info, so try to format it
  28. // using the FormatMessage
  29. // Ignore the return message, if this call fails then I don't
  30. // know what to do.
  31. dwErr = FormatMessage(
  32. FORMAT_MESSAGE_FROM_SYSTEM,
  33. NULL,
  34. hr,
  35. 0,
  36. pszBuffer,
  37. cchBuffer,
  38. NULL);
  39. pszBuffer[cchBuffer-1] = 0;
  40. return HResultFromWin32(dwErr);
  41. }
  42. /*---------------------------------------------------------------------------
  43. TFS Error handling code.
  44. ---------------------------------------------------------------------------*/
  45. struct TFSInternalErrorInfo
  46. {
  47. DWORD m_dwSize; // size of the structure, used for versioning
  48. DWORD m_dwThreadId; // thread id of this error structure
  49. LONG_PTR m_uReserved1; // = 0, reserved for object id
  50. LONG_PTR m_uReserved2; // = 0 for now, reserved for HRESULT component type
  51. DWORD m_hrLow; // HRESULT of the low level error
  52. CString m_stLow; // allocate using HeapAlloc() and GetErrorHeap()
  53. CString m_stHigh; // allocate using HeapAlloc() and GetErrorHeap()
  54. CString m_stGeek; // allocate using HeapAlloc() and GetErrorHeap()
  55. LONG_PTR m_uReserved3; // =0, reserved for error dialog information(?)
  56. LONG_PTR m_uReserved4; // =0, reserved for error dialog information(?)
  57. LONG_PTR m_uReserved5; // =0, reserved for future use
  58. DWORD m_dwFlags; // used to pass info between our objects
  59. // Allocates and serializes a TFSErrorInfo. Used by GetErrorInfo();
  60. TFSErrorInfo * SaveToBlock();
  61. void LoadFromBlock(const TFSErrorInfo *pErr);
  62. };
  63. /*!--------------------------------------------------------------------------
  64. TFSInternalErrorInfo::SaveToBlock
  65. This function converts the internal structure into a TFSErrorInfo
  66. structure (that is allocated on the error heap). It will allocate
  67. all of the data at once.
  68. Author: KennT
  69. ---------------------------------------------------------------------------*/
  70. TFSErrorInfo * TFSInternalErrorInfo::SaveToBlock()
  71. {
  72. DWORD dwSize = 0;
  73. TFSErrorInfo *pError = NULL;
  74. WCHAR * pswz = NULL;
  75. // Determine how large of an allocation we will need
  76. // Need the size of the structure itself
  77. dwSize += sizeof(TFSErrorInfo);
  78. // Need the size of the low-level error string
  79. dwSize += (m_stLow.GetLength() + 1) * sizeof(WCHAR);
  80. dwSize += (m_stHigh.GetLength() + 1) * sizeof(WCHAR);
  81. dwSize += (m_stGeek.GetLength() + 1) * sizeof(WCHAR);
  82. // Allocate a chunk of memory for this
  83. HANDLE hHeap = GetTFSErrorHeap();
  84. if (hHeap)
  85. {
  86. pError = (TFSErrorInfo *) ::HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize);
  87. if (pError)
  88. {
  89. pError->m_dwSize = sizeof(TFSErrorInfo);
  90. // pError->m_dwThreadId = m_dwThreadId;
  91. pError->m_hrLow = m_hrLow;
  92. // pError->m_uReserved1 = m_uReserved1;
  93. pError->m_uReserved2 = m_uReserved2;
  94. pError->m_uReserved3 = m_uReserved3;
  95. pError->m_uReserved4 = m_uReserved4;
  96. pError->m_uReserved5 = m_uReserved5;
  97. // Add the strings to the end of this structure
  98. pswz = (LPWSTR) (pError+1);
  99. StrCpy(pswz, (LPCWSTR) T2CW(m_stLow));
  100. pError->m_pszLow = pswz;
  101. pswz += (StrLenW(pswz) + 1);
  102. StrCpy(pswz, (LPCWSTR) T2CW(m_stHigh));
  103. pError->m_pszHigh = pswz;
  104. pswz += (StrLenW(pswz) + 1);
  105. StrCpy(pswz, (LPCWSTR) T2CW(m_stGeek));
  106. pError->m_pszGeek = pswz;
  107. // Check to see that the size is what we think it is
  108. Assert( (sizeof(TFSErrorInfo) +
  109. (pswz - (LPWSTR)(pError+1)) +
  110. StrLenW(pswz) + 1) <= dwSize );
  111. }
  112. }
  113. return pError;
  114. }
  115. /*!--------------------------------------------------------------------------
  116. TFSInternalErrorInfo::LoadFromBlock
  117. Fills a TFSInternalErrorInfo struct with the information from
  118. a TFSErrorInfo. If pErr is NULL, then we clear this struct (i.e.
  119. fill it in with NULL data).
  120. Author: KennT
  121. ---------------------------------------------------------------------------*/
  122. void TFSInternalErrorInfo::LoadFromBlock(const TFSErrorInfo *pErr)
  123. {
  124. USES_CONVERSION;
  125. if (pErr)
  126. {
  127. m_dwSize = pErr->m_dwSize;
  128. // m_dwThreadId = pErr->m_dwThreadId;
  129. // m_uReserved1 = pErr->m_uReserved1;
  130. m_uReserved2 = pErr->m_uReserved2;
  131. m_uReserved3 = pErr->m_uReserved3;
  132. m_uReserved4 = pErr->m_uReserved4;
  133. m_uReserved5 = pErr->m_uReserved5;
  134. if (pErr->m_hrLow)
  135. m_hrLow = pErr->m_hrLow;
  136. // Overwrite the low-level string if one is provided
  137. if (pErr->m_pszLow)
  138. m_stLow = OLE2CT(pErr->m_pszLow);
  139. // Overwrite the high-level error
  140. if (pErr->m_pszHigh && ((pErr->m_dwFlags & FILLTFSERR_NOCLOBBER) == 0))
  141. m_stHigh = OLE2CT(pErr->m_pszHigh);
  142. // Overwrite the geek-level string if one is provided
  143. if (pErr->m_pszGeek)
  144. m_stGeek = OLE2CT(pErr->m_pszGeek);
  145. }
  146. else
  147. {
  148. // if pErr==NULL, clear out the structure
  149. m_dwSize = 0;
  150. // m_dwThreadId = 0;
  151. // m_uReserved1 = 0;
  152. m_uReserved2 = 0;
  153. m_uReserved3 = 0;
  154. m_uReserved4 = 0;
  155. m_uReserved5 = 0;
  156. m_hrLow = 0;
  157. m_stLow.Empty();
  158. m_stHigh.Empty();
  159. m_stGeek.Empty();
  160. }
  161. }
  162. /*---------------------------------------------------------------------------
  163. Type: TFSInternalErrorList
  164. ---------------------------------------------------------------------------*/
  165. typedef CList<TFSInternalErrorInfo *, TFSInternalErrorInfo *> TFSInternalErrorInfoList;
  166. /*---------------------------------------------------------------------------
  167. Class: TFSErrorObject
  168. This is the central class that manages the error information structures
  169. for the various threads and objects.
  170. This class is thread-safe.
  171. ---------------------------------------------------------------------------*/
  172. class TFSErrorObject : public ITFSError
  173. {
  174. public:
  175. DeclareIUnknownMembers(IMPL);
  176. DeclareITFSErrorMembers(IMPL);
  177. TFSErrorObject();
  178. ~TFSErrorObject();
  179. void Lock();
  180. void Unlock();
  181. HRESULT Init();
  182. HRESULT Cleanup();
  183. HANDLE GetHeap();
  184. HRESULT CreateErrorInfo(DWORD dwThreadId, LONG_PTR uReserved);
  185. HRESULT DestroyErrorInfo(DWORD dwThreadId, LONG_PTR uReserved);
  186. // Looks for the error info that matches up with the dwThreadId
  187. // and uReserved.
  188. TFSInternalErrorInfo * FindErrorInfo(DWORD dwThreadId, LONG_PTR uReserved);
  189. protected:
  190. long m_cRef;
  191. BOOL m_fInitialized; // TRUE if initialized, FALSE otherwise
  192. CRITICAL_SECTION m_critsec;
  193. TFSInternalErrorInfoList m_tfserrList;
  194. HANDLE m_hHeap; // Handle of the heap for this error object
  195. };
  196. TFSErrorObject::TFSErrorObject()
  197. : m_cRef(1),
  198. m_fInitialized(FALSE),
  199. m_hHeap(NULL)
  200. {
  201. InitializeCriticalSection(&m_critsec);
  202. }
  203. TFSErrorObject::~TFSErrorObject()
  204. {
  205. Cleanup();
  206. DeleteCriticalSection(&m_critsec);
  207. }
  208. IMPLEMENT_SIMPLE_QUERYINTERFACE(TFSErrorObject, ITFSError)
  209. STDMETHODIMP_(ULONG) TFSErrorObject::AddRef()
  210. {
  211. return InterlockedIncrement(&m_cRef);
  212. }
  213. STDMETHODIMP_(ULONG) TFSErrorObject::Release()
  214. {
  215. Assert(m_cRef > 0);
  216. if (0 == InterlockedDecrement(&m_cRef))
  217. {
  218. // No need to free this object up since it's static
  219. return 0;
  220. }
  221. return m_cRef;
  222. }
  223. /*!--------------------------------------------------------------------------
  224. TFSErrorObject::Lock
  225. -
  226. Author: KennT
  227. ---------------------------------------------------------------------------*/
  228. void TFSErrorObject::Lock()
  229. {
  230. EnterCriticalSection(&m_critsec);
  231. }
  232. /*!--------------------------------------------------------------------------
  233. TFSErrorObject::Unlock
  234. -
  235. Author: KennT
  236. ---------------------------------------------------------------------------*/
  237. void TFSErrorObject::Unlock()
  238. {
  239. LeaveCriticalSection(&m_critsec);
  240. }
  241. /*!--------------------------------------------------------------------------
  242. TFSErrorObject::Init
  243. -
  244. Author: KennT
  245. ---------------------------------------------------------------------------*/
  246. HRESULT TFSErrorObject::Init()
  247. {
  248. HRESULT hr = hrOK;
  249. Lock();
  250. if (!m_fInitialized)
  251. {
  252. Assert(m_tfserrList.GetCount() == 0);
  253. // Create the heap
  254. m_hHeap = HeapCreate(0, 4096, 0);
  255. if (m_hHeap == NULL)
  256. hr = HRESULT_FROM_WIN32(GetLastError());
  257. if (FHrSucceeded(hr))
  258. m_fInitialized = TRUE;
  259. }
  260. Unlock();
  261. return hr;
  262. }
  263. /*!--------------------------------------------------------------------------
  264. TFSErrorObject::Cleanup
  265. -
  266. Author: KennT
  267. ---------------------------------------------------------------------------*/
  268. HRESULT TFSErrorObject::Cleanup()
  269. {
  270. HRESULT hr = hrOK;
  271. POSITION pos;
  272. TFSInternalErrorInfo * pErr;
  273. Lock();
  274. if (m_fInitialized)
  275. {
  276. while (!m_tfserrList.IsEmpty())
  277. {
  278. delete m_tfserrList.RemoveHead();
  279. }
  280. if (m_hHeap)
  281. {
  282. HeapDestroy(m_hHeap);
  283. m_hHeap = NULL;
  284. }
  285. }
  286. Unlock();
  287. return hr;
  288. }
  289. /*!--------------------------------------------------------------------------
  290. TFSErrorObject::GetHeap
  291. -
  292. Author: KennT
  293. ---------------------------------------------------------------------------*/
  294. HANDLE TFSErrorObject::GetHeap()
  295. {
  296. HANDLE hHeap = NULL;
  297. Lock();
  298. if (m_fInitialized)
  299. hHeap = m_hHeap;
  300. Unlock();
  301. return hHeap;
  302. }
  303. HRESULT TFSErrorObject::CreateErrorInfo(DWORD dwThreadId, LONG_PTR uReserved)
  304. {
  305. HRESULT hr = hrOK;
  306. TFSInternalErrorInfo * pErr = NULL;
  307. COM_PROTECT_TRY
  308. {
  309. if (FindErrorInfo(dwThreadId, uReserved) == NULL)
  310. {
  311. pErr = new TFSInternalErrorInfo;
  312. pErr->LoadFromBlock(NULL);
  313. // Fill in the data with the appropriate fields
  314. pErr->m_dwThreadId = dwThreadId;
  315. pErr->m_uReserved1 = uReserved;
  316. m_tfserrList.AddTail(pErr);
  317. }
  318. }
  319. COM_PROTECT_CATCH;
  320. if (!FHrSucceeded(hr))
  321. delete pErr;
  322. return hr;
  323. }
  324. HRESULT TFSErrorObject::DestroyErrorInfo(DWORD dwThreadId, LONG_PTR uReserved)
  325. {
  326. HRESULT hr = hrOK;
  327. POSITION pos, posTemp;
  328. TFSInternalErrorInfo * pErr;
  329. BOOL bFound = FALSE;
  330. COM_PROTECT_TRY
  331. {
  332. pos = m_tfserrList.GetHeadPosition();
  333. while (pos)
  334. {
  335. posTemp = pos;
  336. pErr = m_tfserrList.GetNext(pos);
  337. if ((pErr->m_dwThreadId == dwThreadId) &&
  338. (pErr->m_uReserved1 == uReserved))
  339. {
  340. m_tfserrList.RemoveAt(posTemp);
  341. delete pErr;
  342. bFound = TRUE;
  343. break;
  344. }
  345. }
  346. if (!bFound)
  347. hr = E_INVALIDARG;
  348. }
  349. COM_PROTECT_CATCH;
  350. return hr;
  351. }
  352. TFSInternalErrorInfo * TFSErrorObject::FindErrorInfo(DWORD dwThreadId, LONG_PTR uReserved)
  353. {
  354. POSITION pos;
  355. POSITION posTemp;
  356. TFSInternalErrorInfo * pErr = NULL;
  357. BOOL bFound = FALSE;
  358. HRESULT hr = hrOK;
  359. COM_PROTECT_TRY
  360. {
  361. pos = m_tfserrList.GetHeadPosition();
  362. while (pos)
  363. {
  364. posTemp = pos;
  365. pErr = m_tfserrList.GetNext(pos);
  366. if ((pErr->m_dwThreadId == dwThreadId) &&
  367. (pErr->m_uReserved1 == uReserved))
  368. {
  369. bFound = TRUE;
  370. break;
  371. }
  372. }
  373. }
  374. COM_PROTECT_CATCH;
  375. return bFound ? pErr : NULL;
  376. }
  377. /*!--------------------------------------------------------------------------
  378. TFSErrorObject::GetErrorInfo
  379. Implementation of ITFSError::GetErrorInfo
  380. Author: KennT
  381. ---------------------------------------------------------------------------*/
  382. STDMETHODIMP TFSErrorObject::GetErrorInfo(LONG_PTR uReserved, TFSErrorInfo **ppErr)
  383. {
  384. HRESULT hr = hrOK;
  385. Lock();
  386. COM_PROTECT_TRY
  387. {
  388. hr = GetErrorInfoForThread(GetCurrentThreadId(), uReserved, ppErr);
  389. }
  390. COM_PROTECT_CATCH;
  391. Unlock();
  392. return hr;
  393. }
  394. /*!--------------------------------------------------------------------------
  395. TFSErrorObject::GetErrorInfoForThread
  396. Implementation of ITFSError::GetErrorInfoForThread
  397. Author: KennT
  398. ---------------------------------------------------------------------------*/
  399. STDMETHODIMP TFSErrorObject::GetErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved, TFSErrorInfo **ppErr)
  400. {
  401. HRESULT hr = hrOK;
  402. TFSInternalErrorInfo * pInternalError;
  403. TFSErrorInfo * pErr = NULL;
  404. if (ppErr == NULL)
  405. return E_INVALIDARG;
  406. *ppErr = NULL;
  407. Lock();
  408. COM_PROTECT_TRY
  409. {
  410. if (!m_fInitialized)
  411. hr = E_FAIL;
  412. else
  413. {
  414. // Can we find the right error object?
  415. pInternalError = FindErrorInfo(dwThreadId, uReserved);
  416. if (pInternalError)
  417. pErr = pInternalError->SaveToBlock();
  418. else
  419. hr = E_INVALIDARG;
  420. *ppErr = pErr;
  421. }
  422. }
  423. COM_PROTECT_CATCH;
  424. Unlock();
  425. return hr;
  426. }
  427. /*!--------------------------------------------------------------------------
  428. TFSErrorObject::SetErrorInfo
  429. Implementation of ITFSError::SetErrorInfo
  430. Author: KennT
  431. ---------------------------------------------------------------------------*/
  432. STDMETHODIMP TFSErrorObject::SetErrorInfo(LONG_PTR uReserved, const TFSErrorInfo *pErr)
  433. {
  434. HRESULT hr = hrOK;
  435. Lock();
  436. COM_PROTECT_TRY
  437. {
  438. hr = SetErrorInfoForThread(GetCurrentThreadId(), uReserved, pErr);
  439. }
  440. COM_PROTECT_CATCH;
  441. Unlock();
  442. return hr;
  443. }
  444. /*!--------------------------------------------------------------------------
  445. TFSErrorObject::SetErrorInfoForThread
  446. Implementation of ITFSError::SetErrorInfoForThread
  447. Author: KennT
  448. ---------------------------------------------------------------------------*/
  449. STDMETHODIMP TFSErrorObject::SetErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved, const TFSErrorInfo *pErr)
  450. {
  451. HRESULT hr = hrOK;
  452. TFSInternalErrorInfo * pInternalError;
  453. Lock();
  454. COM_PROTECT_TRY
  455. {
  456. if (!m_fInitialized)
  457. hr = E_FAIL;
  458. else
  459. {
  460. // Can we find the right error object?
  461. pInternalError = FindErrorInfo(dwThreadId, uReserved);
  462. if (pInternalError)
  463. {
  464. pInternalError->LoadFromBlock(pErr);
  465. }
  466. else
  467. hr = E_INVALIDARG;
  468. }
  469. }
  470. COM_PROTECT_CATCH;
  471. Unlock();
  472. return hr;
  473. }
  474. /*!--------------------------------------------------------------------------
  475. TFSErrorObject::ClearErrorInfo
  476. Implementation of ITFSError::ClearErrorInfo
  477. Author: KennT
  478. ---------------------------------------------------------------------------*/
  479. STDMETHODIMP TFSErrorObject::ClearErrorInfo(LONG_PTR uReserved)
  480. {
  481. HRESULT hr = hrOK;
  482. Lock();
  483. COM_PROTECT_TRY
  484. {
  485. hr = ClearErrorInfoForThread(GetCurrentThreadId(), uReserved);
  486. }
  487. COM_PROTECT_CATCH;
  488. Unlock();
  489. return hr;
  490. }
  491. /*!--------------------------------------------------------------------------
  492. TFSErrorObject::ClearErrorInfoForThread
  493. Implementation of ITFSError::ClearErrorInfoForThread
  494. Author: KennT
  495. ---------------------------------------------------------------------------*/
  496. STDMETHODIMP TFSErrorObject::ClearErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved)
  497. {
  498. HRESULT hr = hrOK;
  499. TFSInternalErrorInfo * pInternalError;
  500. Lock();
  501. COM_PROTECT_TRY
  502. {
  503. if (!m_fInitialized)
  504. hr = E_FAIL;
  505. else
  506. {
  507. // Can we find the right error object?
  508. pInternalError = FindErrorInfo(dwThreadId, uReserved);
  509. if (pInternalError)
  510. {
  511. // Clear the information out of the internal block
  512. pInternalError->LoadFromBlock(NULL);
  513. }
  514. else
  515. hr = E_INVALIDARG;
  516. }
  517. }
  518. COM_PROTECT_CATCH;
  519. Unlock();
  520. return hr;
  521. }
  522. /*---------------------------------------------------------------------------
  523. This is a static object that lives in the process space. It does not
  524. get dynamically created or destroyed.
  525. ---------------------------------------------------------------------------*/
  526. static TFSErrorObject s_tfsErrorObject;
  527. /*---------------------------------------------------------------------------
  528. Global API functions
  529. ---------------------------------------------------------------------------*/
  530. /*!--------------------------------------------------------------------------
  531. InitializeTFSError
  532. -
  533. Author: KennT
  534. ---------------------------------------------------------------------------*/
  535. TFSCORE_API(HRESULT) InitializeTFSError()
  536. {
  537. return s_tfsErrorObject.Init();
  538. }
  539. /*!--------------------------------------------------------------------------
  540. CleanupTFSError
  541. -
  542. Author: KennT
  543. ---------------------------------------------------------------------------*/
  544. TFSCORE_API(HRESULT) CleanupTFSError()
  545. {
  546. return s_tfsErrorObject.Cleanup();
  547. }
  548. /*!--------------------------------------------------------------------------
  549. GetTFSErrorObject
  550. -
  551. Author: KennT
  552. ---------------------------------------------------------------------------*/
  553. TFSCORE_API(ITFSError *) GetTFSErrorObject()
  554. {
  555. return &s_tfsErrorObject;
  556. }
  557. /*!--------------------------------------------------------------------------
  558. GetTFSErrorHeap
  559. -
  560. Author: KennT
  561. ---------------------------------------------------------------------------*/
  562. TFSCORE_API(HANDLE) GetTFSErrorHeap()
  563. {
  564. return s_tfsErrorObject.GetHeap();
  565. }
  566. /*!--------------------------------------------------------------------------
  567. CreateTFSErrorInfo
  568. -
  569. Author: KennT
  570. ---------------------------------------------------------------------------*/
  571. TFSCORE_API(HRESULT) CreateTFSErrorInfo(LONG_PTR uReserved)
  572. {
  573. return CreateTFSErrorInfoForThread(GetCurrentThreadId(), uReserved);
  574. }
  575. /*!--------------------------------------------------------------------------
  576. CreateTFSErrorInfoForThread
  577. -
  578. Author: KennT
  579. ---------------------------------------------------------------------------*/
  580. TFSCORE_API(HRESULT) CreateTFSErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved)
  581. {
  582. return s_tfsErrorObject.CreateErrorInfo(dwThreadId, uReserved);
  583. }
  584. /*!--------------------------------------------------------------------------
  585. DestroyTFSErrorInfo
  586. -
  587. Author: KennT
  588. ---------------------------------------------------------------------------*/
  589. TFSCORE_API(HRESULT) DestroyTFSErrorInfo(LONG_PTR uReserved)
  590. {
  591. return DestroyTFSErrorInfoForThread(GetCurrentThreadId(), uReserved);
  592. }
  593. /*!--------------------------------------------------------------------------
  594. DestroyTFSErrorInfoForThread
  595. -
  596. Author: KennT
  597. ---------------------------------------------------------------------------*/
  598. TFSCORE_API(HRESULT) DestroyTFSErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved)
  599. {
  600. return s_tfsErrorObject.DestroyErrorInfo(dwThreadId, uReserved);
  601. }
  602. TFSCORE_API(HRESULT) ClearTFSErrorInfo(LONG_PTR uReserved)
  603. {
  604. return ClearTFSErrorInfoForThread(GetCurrentThreadId(), uReserved);
  605. }
  606. TFSCORE_API(HRESULT) ClearTFSErrorInfoForThread(DWORD dwThreadId, LONG_PTR uReserved)
  607. {
  608. return s_tfsErrorObject.ClearErrorInfoForThread(dwThreadId, uReserved);
  609. }
  610. /*!--------------------------------------------------------------------------
  611. DisplayTFSErrorMessage
  612. -
  613. Author: KennT
  614. ---------------------------------------------------------------------------*/
  615. TFSCORE_API(HRESULT) DisplayTFSErrorMessage(HWND hWndParent)
  616. {
  617. CString stTitle;
  618. stTitle.LoadString(AFX_IDS_APP_TITLE);
  619. HRESULT hr = hrOK;
  620. CString st;
  621. TFSErrorInfo * pErr = NULL;
  622. BOOL fQuit;
  623. MSG msgT;
  624. // Format the string with the text for the current error message
  625. GetTFSErrorObject()->GetErrorInfo(0, &pErr);
  626. if (pErr && !FHrSucceeded(pErr->m_hrLow))
  627. {
  628. if (pErr->m_pszHigh && pErr->m_pszLow)
  629. {
  630. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  631. AfxFormatString2(st, IDS_ERROR_FORMAT2,
  632. pErr->m_pszHigh, pErr->m_pszLow);
  633. }
  634. else if (pErr->m_pszHigh || pErr->m_pszLow)
  635. {
  636. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  637. AfxFormatString1(st, IDS_ERROR_FORMAT1,
  638. pErr->m_pszHigh ? pErr->m_pszHigh : pErr->m_pszLow);
  639. }
  640. // Is there a WM_QUIT message in the queue, if so remove it.
  641. fQuit = ::PeekMessage(&msgT, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
  642. ::MessageBox(hWndParent, (LPCTSTR) st, (LPCTSTR) stTitle,
  643. MB_OK | MB_ICONERROR | /*MB_DEFAULT_DESKTOP_ONLY | --ft:removed as per bug #233282*/
  644. MB_SETFOREGROUND);
  645. // If there was a quit message, add it back into the queue
  646. if (fQuit)
  647. ::PostQuitMessage((int)msgT.wParam);
  648. if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0)
  649. {
  650. CString stHresult;
  651. // Bring up another message box with the geek message
  652. // if there is one
  653. if (pErr->m_pszGeek)
  654. {
  655. {
  656. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  657. stHresult.Format(_T("%08lx"), pErr->m_hrLow);
  658. AfxFormatString2(st, IDS_ERROR_MORE_INFORMATION, stHresult, pErr->m_pszGeek);
  659. }
  660. // Is there a WM_QUIT message in the queue, if so remove it.
  661. fQuit = ::PeekMessage(&msgT, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
  662. ::MessageBox(hWndParent, (LPCTSTR) st, (LPCTSTR) stTitle,
  663. MB_OK | MB_ICONERROR | /*MB_DEFAULT_DESKTOP_ONLY | --ft:removed as per bug #233282*/
  664. MB_SETFOREGROUND);
  665. // If there was a quit message, add it back into the queue
  666. if (fQuit)
  667. ::PostQuitMessage((int)msgT.wParam);
  668. }
  669. }
  670. TFSErrorInfoFree(pErr);
  671. pErr = NULL;
  672. }
  673. else
  674. hr = E_FAIL;
  675. return hr;
  676. }
  677. TFSCORE_API(HRESULT) FillTFSError(LONG_PTR uReserved,
  678. HRESULT hrLow,
  679. DWORD dwFlags,
  680. LPCTSTR pszHigh,
  681. LPCTSTR pszLow,
  682. LPCTSTR pszGeek)
  683. {
  684. TFSErrorInfo es;
  685. HRESULT hr = hrOK;
  686. USES_CONVERSION;
  687. ::ZeroMemory(&es, sizeof(es));
  688. es.m_dwSize = sizeof(TFSErrorInfo);
  689. es.m_uReserved2 = 0;
  690. es.m_hrLow = hrLow;
  691. if (dwFlags & FILLTFSERR_LOW)
  692. es.m_pszLow = T2COLE(pszLow);
  693. if (dwFlags & FILLTFSERR_HIGH)
  694. es.m_pszHigh = T2COLE(pszHigh);
  695. if (dwFlags & FILLTFSERR_GEEK)
  696. es.m_pszGeek = T2COLE(pszGeek);
  697. es.m_uReserved3 = 0;
  698. es.m_uReserved4 = 0;
  699. es.m_uReserved5 = 0;
  700. es.m_dwFlags = dwFlags;
  701. GetTFSErrorObject()->SetErrorInfo(uReserved, &es);
  702. return hr;
  703. }
  704. TFSCORE_API(HRESULT) FillTFSErrorId(LONG_PTR uReserved,
  705. HRESULT hrLow,
  706. DWORD dwFlags,
  707. UINT nHigh,
  708. UINT nLow,
  709. UINT nGeek)
  710. {
  711. CString stHigh, stLow, stGeek;
  712. if ((dwFlags & FILLTFSERR_HIGH) && nHigh)
  713. stHigh.LoadString(nHigh);
  714. if ((dwFlags & FILLTFSERR_LOW) && nLow)
  715. stLow.LoadString(nLow);
  716. if ((dwFlags & FILLTFSERR_GEEK) && nGeek)
  717. stGeek.LoadString(nGeek);
  718. return FillTFSError(uReserved, hrLow, dwFlags, (LPCTSTR) stHigh,
  719. (LPCTSTR) stLow, (LPCTSTR) stGeek);
  720. }
  721. TFSCORE_API(void) AddSystemErrorMessage(HRESULT hr)
  722. {
  723. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  724. if (!FHrSucceeded(hr))
  725. {
  726. TCHAR szBuffer[4096];
  727. CString st, stHr;
  728. FormatError(hr, szBuffer, DimensionOf(szBuffer));
  729. stHr.Format(_T("%08lx"), hr);
  730. AfxFormatString2(st, IDS_ERROR_SYSTEM_ERROR_FORMAT,
  731. szBuffer, (LPCTSTR) stHr);
  732. FillTFSError(0, hr, FILLTFSERR_LOW, NULL, (LPCTSTR) st, NULL);
  733. }
  734. }
  735. TFSCORE_API(void) AddWin32ErrorMessage(DWORD dwErr)
  736. {
  737. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  738. if (dwErr != ERROR_SUCCESS)
  739. {
  740. TCHAR szBuffer[4096];
  741. CString st, stHr;
  742. FormatError(dwErr, szBuffer, DimensionOf(szBuffer));
  743. stHr.Format(_T("%08lx"), dwErr);
  744. AfxFormatString2(st, IDS_ERROR_SYSTEM_ERROR_FORMAT,
  745. szBuffer, (LPCTSTR) stHr);
  746. FillTFSError(0, HResultFromWin32(dwErr), FILLTFSERR_LOW, NULL, (LPCTSTR) st, NULL);
  747. }
  748. }
  749. TFSCORE_API(HRESULT) GetTFSErrorInfo(TFSErrorInfo **ppErrInfo)
  750. {
  751. return GetTFSErrorInfoForThread(GetCurrentThreadId(), ppErrInfo);
  752. }
  753. TFSCORE_API(HRESULT) SetTFSErrorInfo(const TFSErrorInfo *pErrInfo)
  754. {
  755. return SetTFSErrorInfoForThread(GetCurrentThreadId(), pErrInfo);
  756. }
  757. TFSCORE_API(HRESULT) GetTFSErrorInfoForThread(DWORD dwThreadId, TFSErrorInfo **ppErrInfo)
  758. {
  759. return GetTFSErrorObject()->GetErrorInfoForThread(dwThreadId, 0, ppErrInfo);
  760. }
  761. TFSCORE_API(HRESULT) SetTFSErrorInfoForThread(DWORD dwThreadId, const TFSErrorInfo *pErrInfo)
  762. {
  763. return GetTFSErrorObject()->SetErrorInfoForThread(dwThreadId, 0, pErrInfo);
  764. }
  765. TFSCORE_API(HRESULT) TFSErrorInfoFree(TFSErrorInfo *pErrInfo)
  766. {
  767. HANDLE hHeap = GetTFSErrorHeap();
  768. if (hHeap)
  769. {
  770. ::HeapFree(hHeap, 0, pErrInfo);
  771. }
  772. return hrOK;
  773. }