summaryrefslogtreecommitdiff
path: root/src/utilcode/posterror.cpp
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/utilcode/posterror.cpp
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/utilcode/posterror.cpp')
-rw-r--r--src/utilcode/posterror.cpp404
1 files changed, 404 insertions, 0 deletions
diff --git a/src/utilcode/posterror.cpp b/src/utilcode/posterror.cpp
new file mode 100644
index 0000000000..0ae48aab71
--- /dev/null
+++ b/src/utilcode/posterror.cpp
@@ -0,0 +1,404 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//*****************************************************************************
+// PostErrors.cpp
+//
+// This module contains the error handling/posting code for the engine. It
+// is assumed that all methods may be called by a dispatch client, and therefore
+// errors are always posted using IErrorInfo.
+//
+
+//*****************************************************************************
+#include "stdafx.h" // Standard header.
+
+#ifndef FEATURE_UTILCODE_NO_DEPENDENCIES
+
+#include <utilcode.h> // Utility helpers.
+#include <corerror.h>
+#include "../dlls/mscorrc/resource.h"
+#include "ex.h"
+
+#include <posterror.h>
+
+#if !defined(lengthof)
+#define lengthof(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+// Local prototypes.
+HRESULT FillErrorInfo(LPCWSTR szMsg, DWORD dwHelpContext);
+
+//*****************************************************************************
+// Function that we'll expose to the outside world to fire off the shutdown method
+//*****************************************************************************
+#ifdef SHOULD_WE_CLEANUP
+void ShutdownCompRC()
+{
+ CCompRC::ShutdownDefaultResourceDll();
+}
+#endif /* SHOULD_WE_CLEANUP */
+
+void GetResourceCultureCallbacks(
+ FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
+ FPGETTHREADUICULTUREID* fpGetThreadUICultureId)
+{
+ WRAPPER_NO_CONTRACT;
+ CCompRC::GetDefaultCallbacks(
+ fpGetThreadUICultureNames,
+ fpGetThreadUICultureId
+ );
+}
+//*****************************************************************************
+// Set callbacks to get culture info
+//*****************************************************************************
+void SetResourceCultureCallbacks(
+ FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
+ FPGETTHREADUICULTUREID fpGetThreadUICultureId // TODO: Don't rely on the LCID, only the name
+)
+{
+ WRAPPER_NO_CONTRACT;
+ CCompRC::SetDefaultCallbacks(
+ fpGetThreadUICultureNames,
+ fpGetThreadUICultureId
+ );
+
+}
+
+//*****************************************************************************
+// Public function to load a resource string
+//*****************************************************************************
+STDAPI UtilLoadStringRC(
+ UINT iResourceID,
+ __out_ecount(iMax) LPWSTR szBuffer,
+ int iMax,
+ int bQuiet
+)
+{
+ WRAPPER_NO_CONTRACT;
+ return UtilLoadResourceString(bQuiet? CCompRC::Optional : CCompRC::Required,iResourceID, szBuffer, iMax);
+}
+
+HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax)
+{
+ CONTRACTL
+ {
+ DISABLED(NOTHROW);
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ HRESULT retVal = E_OUTOFMEMORY;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ SString::Startup();
+ EX_TRY
+ {
+ CCompRC *pResourceDLL = CCompRC::GetDefaultResourceDll();
+
+ if (pResourceDLL != NULL)
+ {
+ retVal = pResourceDLL->LoadString(eCategory, iResourceID, szBuffer, iMax);
+ }
+ }
+ EX_CATCH
+ {
+ // Catch any errors and return E_OUTOFMEMORY;
+ retVal = E_OUTOFMEMORY;
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+ END_SO_INTOLERANT_CODE;
+
+ return retVal;
+}
+
+#ifdef FEATURE_USE_LCID
+STDAPI UtilLoadStringRCEx(
+ LCID lcid,
+ UINT iResourceID,
+ __out_ecount(iMax) LPWSTR szBuffer,
+ int iMax,
+ int bQuiet,
+ int *pcwchUsed
+)
+{
+ CONTRACTL
+ {
+ DISABLED(NOTHROW);
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ HRESULT retVal = E_OUTOFMEMORY;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+ EX_TRY
+ {
+ SString::Startup();
+ CCompRC *pResourceDLL = CCompRC::GetDefaultResourceDll();
+
+ if (pResourceDLL != NULL)
+ {
+ retVal = pResourceDLL->LoadString(bQuiet? CCompRC::Optional : CCompRC::Required,lcid, iResourceID, szBuffer, iMax, pcwchUsed);
+ }
+ }
+ EX_CATCH
+ {
+ // Catch any errors and return E_OUTOFMEMORY;
+ retVal = E_OUTOFMEMORY;
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+ END_SO_INTOLERANT_CODE;
+
+ return retVal;
+}
+#endif //FEATURE_USE_LCID
+
+//*****************************************************************************
+// Format a Runtime Error message.
+//*****************************************************************************
+HRESULT __cdecl FormatRuntimeErrorVa(
+ __inout_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format.
+ ULONG cchMsg, // Size of buffer, characters.
+ HRESULT hrRpt, // The HR to report.
+ va_list marker) // Optional args.
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ WCHAR rcBuf[512]; // Resource string.
+ HRESULT hr;
+
+ // Ensure nul termination.
+ *rcMsg = W('\0');
+
+ // If this is one of our errors or if it is simply a resource ID, then grab the error from the rc file.
+ if ((HRESULT_FACILITY(hrRpt) == FACILITY_URT) || (HIWORD(hrRpt) == 0))
+ {
+ hr = UtilLoadStringRC(LOWORD(hrRpt), rcBuf, NumItems(rcBuf), true);
+ if (hr == S_OK)
+ {
+ _vsnwprintf_s(rcMsg, cchMsg, _TRUNCATE, rcBuf, marker);
+ }
+ }
+ // Otherwise it isn't one of ours, so we need to see if the system can
+ // find the text for it.
+ else
+ {
+#ifdef FEATURE_USE_LCID
+ if (WszFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, hrRpt, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ rcMsg, cchMsg, 0/*<TODO>@todo: marker</TODO>*/))
+#else
+ if (WszFormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, hrRpt, 0,
+ rcMsg, cchMsg, 0/*<TODO>@todo: marker</TODO>*/))
+#endif
+ {
+ hr = S_OK;
+
+ // System messages contain a trailing \r\n, which we don't want normally.
+ size_t iLen = wcslen(rcMsg);
+ if (iLen > 3 && rcMsg[iLen - 2] == '\r' && rcMsg[iLen - 1] == '\n')
+ rcMsg[iLen - 2] = '\0';
+ }
+ else
+ hr = HRESULT_FROM_GetLastError();
+ }
+
+ // If we failed to find the message anywhere, then issue a hard coded message.
+ if (FAILED(hr))
+ {
+ _snwprintf_s(rcMsg, cchMsg, _TRUNCATE, W("Common Language Runtime Internal error: 0x%08x"), hrRpt);
+ DEBUG_STMT(DbgWriteEx(rcMsg));
+ }
+
+ return hrRpt;
+} // FormatRuntimeErrorVa
+
+//*****************************************************************************
+// Format a Runtime Error message, varargs.
+//*****************************************************************************
+HRESULT __cdecl FormatRuntimeError(
+ __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format.
+ ULONG cchMsg, // Size of buffer, characters.
+ HRESULT hrRpt, // The HR to report.
+ ...) // Optional args.
+{
+ WRAPPER_NO_CONTRACT;
+ va_list marker; // User text.
+ va_start(marker, hrRpt);
+ hrRpt = FormatRuntimeErrorVa(rcMsg, cchMsg, hrRpt, marker);
+ va_end(marker);
+ return hrRpt;
+}
+
+#ifdef FEATURE_COMINTEROP
+//*****************************************************************************
+// Create, fill out and set an error info object. Note that this does not fill
+// out the IID for the error object; that is done elsewhere.
+//*****************************************************************************
+HRESULT FillErrorInfo( // Return status.
+ LPCWSTR szMsg, // Error message.
+ DWORD dwHelpContext) // Help context.
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ ICreateErrorInfo *pICreateErr; // Error info creation Iface pointer.
+ IErrorInfo *pIErrInfo = NULL; // The IErrorInfo interface.
+ HRESULT hr; // Return status.
+
+ // Get the ICreateErrorInfo pointer.
+ hr = S_OK;
+ EX_TRY
+ {
+ hr = CreateErrorInfo(&pICreateErr);
+ }
+ EX_CATCH
+ {
+ hr = GET_EXCEPTION()->GetHR();
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+ if (FAILED(hr))
+ return (hr);
+
+ // Set message text description.
+ if (FAILED(hr = pICreateErr->SetDescription((LPWSTR) szMsg)))
+ goto Exit1;
+
+ // suppress PreFast warning about passing literal string to non-const API.
+ // This API (ICreateErrorInfo::SetHelpFile) is documented to take a const argument, but
+ // we can't put const in the signature because it would break existing implementors of
+ // the API.
+#ifdef _PREFAST_
+#pragma prefast(push)
+#pragma warning(disable:6298)
+#endif
+
+ // Set the help file and help context.
+ //<TODO>@todo: we don't have a help file yet.</TODO>
+ if (FAILED(hr = pICreateErr->SetHelpFile(const_cast<wchar_t*>(W("complib.hlp")))) ||
+ FAILED(hr = pICreateErr->SetHelpContext(dwHelpContext)))
+ goto Exit1;
+
+#ifdef _PREFAST_
+#pragma prefast(pop)
+#endif
+
+ // Get the IErrorInfo pointer.
+ if (FAILED(hr = pICreateErr->QueryInterface(IID_IErrorInfo, (PVOID *) &pIErrInfo)))
+ goto Exit1;
+
+ // Save the error and release our local pointers.
+ {
+ // If we get here, we have loaded oleaut32.dll.
+ CONTRACT_VIOLATION(ThrowsViolation);
+ SetErrorInfo(0L, pIErrInfo);
+ }
+
+Exit1:
+ pICreateErr->Release();
+ if (pIErrInfo) {
+ pIErrInfo->Release();
+ }
+ return hr;
+}
+#endif // FEATURE_COMINTEROP
+
+//*****************************************************************************
+// This function will post an error for the client. If the LOWORD(hrRpt) can
+// be found as a valid error message, then it is loaded and formatted with
+// the arguments passed in. If it cannot be found, then the error is checked
+// against FormatMessage to see if it is a system error. System errors are
+// not formatted so no add'l parameters are required. If any errors in this
+// process occur, hrRpt is returned for the client with no error posted.
+//*****************************************************************************
+extern "C"
+HRESULT __cdecl PostErrorVA( // Returned error.
+ HRESULT hrRpt, // Reported error.
+ va_list marker) // Error arguments.
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ ENTRY_POINT;
+ }
+ CONTRACTL_END;
+
+#ifdef FEATURE_COMINTEROP
+
+ const DWORD cchMsg = 4096;
+ WCHAR *rcMsg = (WCHAR*)alloca(cchMsg * sizeof(WCHAR)); // Error message.
+ HRESULT hr;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ // Return warnings without text.
+ if (!FAILED(hrRpt))
+ goto ErrExit;
+
+ // If we are already out of memory or out of stack or the thread is in some bad state,
+ // we don't want throw gasoline on the fire by calling ErrorInfo stuff below (which can
+ // trigger a delayload of oleaut32.dll). We don't need to embellish transient errors
+ // so just return this without text.
+ if (Exception::IsTransient(hrRpt))
+ {
+ goto ErrExit;
+ }
+
+ // Format the error.
+ FormatRuntimeErrorVa(rcMsg, cchMsg, hrRpt, marker);
+
+ // Turn the error into a posted error message. If this fails, we still
+ // return the original error message since a message caused by our error
+ // handling system isn't going to give you a clue about the original error.
+ hr = FillErrorInfo(rcMsg, LOWORD(hrRpt));
+ _ASSERTE(hr == S_OK);
+
+ErrExit:
+
+ END_ENTRYPOINT_NOTHROW;
+
+#endif // FEATURE_COMINTEROP
+
+ return (hrRpt);
+} // PostErrorVA
+
+#endif //!FEATURE_UTILCODE_NO_DEPENDENCIES
+
+//*****************************************************************************
+// This function will post an error for the client. If the LOWORD(hrRpt) can
+// be found as a valid error message, then it is loaded and formatted with
+// the arguments passed in. If it cannot be found, then the error is checked
+// against FormatMessage to see if it is a system error. System errors are
+// not formatted so no add'l parameters are required. If any errors in this
+// process occur, hrRpt is returned for the client with no error posted.
+//*****************************************************************************
+extern "C"
+HRESULT __cdecl PostError(
+ HRESULT hrRpt, // Reported error.
+ ...) // Error arguments.
+{
+#ifndef FEATURE_UTILCODE_NO_DEPENDENCIES
+ WRAPPER_NO_CONTRACT;
+ va_list marker; // User text.
+ va_start(marker, hrRpt);
+ hrRpt = PostErrorVA(hrRpt, marker);
+ va_end(marker);
+#endif //!FEATURE_UTILCODE_NO_DEPENDENCIES
+ return hrRpt;
+}