screrror.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "ParserPch.h"
  6. #pragma hdrstop
  7. #include "errstr.h"
  8. void CopyException (EXCEPINFO *peiDest, const EXCEPINFO *peiSource)
  9. {
  10. FreeExcepInfo(peiDest);
  11. *peiDest = *peiSource;
  12. if (peiSource->bstrSource) {
  13. peiDest->bstrSource =
  14. SysAllocStringLen(peiSource->bstrSource, SysStringLen(peiSource->bstrSource));
  15. }
  16. if (peiSource->bstrDescription) {
  17. peiDest->bstrDescription =
  18. SysAllocStringLen(peiSource->bstrDescription, SysStringLen(peiSource->bstrDescription));
  19. }
  20. if (peiSource->bstrHelpFile) {
  21. peiDest->bstrHelpFile =
  22. SysAllocStringLen(peiSource->bstrHelpFile, SysStringLen(peiSource->bstrHelpFile));
  23. }
  24. }
  25. /***
  26. *BOOL FSupportsErrorInfo
  27. *Purpose:
  28. * Answers if the given object supports the Rich Error mechanism
  29. * on the given interface.
  30. *
  31. *Entry:
  32. * punk = the object
  33. * riid = the IID of the interface on the object
  34. *
  35. *Exit:
  36. * return value = BOOL
  37. *
  38. ***********************************************************************/
  39. BOOL FSupportsErrorInfo(IUnknown *punk, REFIID riid)
  40. {
  41. BOOL fSupports;
  42. ISupportErrorInfo *psupport;
  43. fSupports = FALSE;
  44. if(SUCCEEDED(punk->QueryInterface(__uuidof(ISupportErrorInfo), (void **)&psupport)))
  45. {
  46. if(NOERROR == psupport->InterfaceSupportsErrorInfo(riid))
  47. fSupports = TRUE;
  48. psupport->Release();
  49. }
  50. return fSupports;
  51. }
  52. /***
  53. *PUBLIC HRESULT GetErrorInfo
  54. *Purpose:
  55. * Filling the given EXCEPINFO structure from the contents of
  56. * the current OLE error object (if any).
  57. *
  58. *Entry:
  59. * pexcepinfo = pointer to caller allocated EXCEPINFO to fillin.
  60. *
  61. *Exit:
  62. * return value = HRESULT. S_OK if obtained info, else S_FALSE
  63. *
  64. *Note:
  65. * This routine assumes that the given EXCEPINFO does *not* contain
  66. * any strings that need to be freed before its contents are set.
  67. *
  68. ***********************************************************************/
  69. HRESULT GetErrorInfo(EXCEPINFO *pexcepinfo)
  70. {
  71. HRESULT hr;
  72. memset(pexcepinfo, 0, sizeof(*pexcepinfo));
  73. IErrorInfo *perrinfo;
  74. // GetErrorInfo returns S_FALSE if there is no rich error info
  75. // and S_OK if there is.
  76. if(NOERROR == (hr = GetErrorInfo(0L, &perrinfo)))
  77. {
  78. perrinfo->GetSource(&pexcepinfo->bstrSource);
  79. perrinfo->GetDescription(&pexcepinfo->bstrDescription);
  80. perrinfo->GetHelpFile(&pexcepinfo->bstrHelpFile);
  81. perrinfo->GetHelpContext(&pexcepinfo->dwHelpContext);
  82. perrinfo->Release();
  83. }
  84. return hr;
  85. }
  86. /***************************************************************************
  87. HRESULT mapping
  88. ***************************************************************************/
  89. template <rtErrors errnum> class ErrorTypeMap;
  90. #define RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) \
  91. template <> class ErrorTypeMap<name> \
  92. { \
  93. public: \
  94. static const ErrorTypeEnum Type = jst; \
  95. };
  96. #define RT_PUBLICERROR_MSG(name, errnum, str1, str2, jst, errorNumSource) RT_ERROR_MSG(name, errnum, str1, str2, jst, errorNumSource)
  97. #include "rterrors.h"
  98. #undef RT_PUBLICERROR_MSG
  99. #undef RT_ERROR_MSG
  100. struct MHR
  101. {
  102. HRESULT hrIn;
  103. HRESULT hrOut;
  104. ErrorTypeEnum errorType;
  105. };
  106. // This table maps OLE errors to JScript errors. The comment on each line
  107. // shows the numeric value. The table must be sorted so we can do a binary
  108. // search on it.
  109. #define MAPHR(in, out) { HR(in), out, ErrorTypeMap<out>::Type }
  110. const MHR g_rgmhr[] =
  111. {
  112. // FACILITY_NULL errors
  113. #if _WIN32 || _WIN64
  114. /*0x80004001*/ MAPHR(E_NOTIMPL, VBSERR_ActionNotSupported),
  115. /*0x80004002*/ MAPHR(E_NOINTERFACE, VBSERR_OLENotSupported),
  116. #else
  117. #error Neither __WIN32, nor _WIN64 is defined
  118. #endif
  119. // FACILITY_DISPATCH - IDispatch errors.
  120. /*0x80020001*/ MAPHR(DISP_E_UNKNOWNINTERFACE, VBSERR_OLENoPropOrMethod),
  121. /*0x80020003*/ MAPHR(DISP_E_MEMBERNOTFOUND, VBSERR_OLENoPropOrMethod),
  122. /*0x80020004*/ MAPHR(DISP_E_PARAMNOTFOUND, VBSERR_NamedParamNotFound),
  123. /*0x80020005*/ MAPHR(DISP_E_TYPEMISMATCH, VBSERR_TypeMismatch),
  124. /*0x80020006*/ MAPHR(DISP_E_UNKNOWNNAME, VBSERR_OLENoPropOrMethod),
  125. /*0x80020007*/ MAPHR(DISP_E_NONAMEDARGS, VBSERR_NamedArgsNotSupported),
  126. /*0x80020008*/ MAPHR(DISP_E_BADVARTYPE, VBSERR_InvalidTypeLibVariable),
  127. /*0x8002000A*/ MAPHR(DISP_E_OVERFLOW, VBSERR_Overflow),
  128. /*0x8002000B*/ MAPHR(DISP_E_BADINDEX, VBSERR_OutOfBounds),
  129. /*0x8002000C*/ MAPHR(DISP_E_UNKNOWNLCID, VBSERR_LocaleSettingNotSupported),
  130. /*0x8002000D*/ MAPHR(DISP_E_ARRAYISLOCKED, VBSERR_ArrayLocked),
  131. /*0x8002000E*/ MAPHR(DISP_E_BADPARAMCOUNT, VBSERR_FuncArityMismatch),
  132. /*0x8002000F*/ MAPHR(DISP_E_PARAMNOTOPTIONAL, VBSERR_ParameterNotOptional),
  133. /*0x80020011*/ MAPHR(DISP_E_NOTACOLLECTION, VBSERR_NotEnum),
  134. // FACILITY_DISPATCH - Typelib errors.
  135. /*0x8002802F*/ MAPHR(TYPE_E_DLLFUNCTIONNOTFOUND, VBSERR_InvalidDllFunctionName),
  136. /*0x80028CA0*/ MAPHR(TYPE_E_TYPEMISMATCH, VBSERR_TypeMismatch),
  137. /*0x80028CA1*/ MAPHR(TYPE_E_OUTOFBOUNDS, VBSERR_OutOfBounds),
  138. /*0x80028CA2*/ MAPHR(TYPE_E_IOERROR, VBSERR_IOError),
  139. /*0x80028CA3*/ MAPHR(TYPE_E_CANTCREATETMPFILE, VBSERR_CantCreateTmpFile),
  140. /*0x80029C4A*/ MAPHR(TYPE_E_CANTLOADLIBRARY, VBSERR_DLLLoadErr),
  141. // FACILITY_STORAGE errors
  142. /*0x80030002*/ MAPHR(STG_E_FILENOTFOUND, VBSERR_OLEFileNotFound),
  143. /*0x80030003*/ MAPHR(STG_E_PATHNOTFOUND, VBSERR_PathNotFound),
  144. /*0x80030004*/ MAPHR(STG_E_TOOMANYOPENFILES, VBSERR_TooManyFiles),
  145. /*0x80030005*/ MAPHR(STG_E_ACCESSDENIED, VBSERR_PermissionDenied),
  146. /*0x80030008*/ MAPHR(STG_E_INSUFFICIENTMEMORY, VBSERR_OutOfMemory),
  147. /*0x80030012*/ MAPHR(STG_E_NOMOREFILES, VBSERR_TooManyFiles),
  148. /*0x80030013*/ MAPHR(STG_E_DISKISWRITEPROTECTED, VBSERR_PermissionDenied),
  149. /*0x8003001D*/ MAPHR(STG_E_WRITEFAULT, VBSERR_IOError),
  150. /*0x8003001E*/ MAPHR(STG_E_READFAULT, VBSERR_IOError),
  151. /*0x80030020*/ MAPHR(STG_E_SHAREVIOLATION, VBSERR_PathFileAccess),
  152. /*0x80030021*/ MAPHR(STG_E_LOCKVIOLATION, VBSERR_PermissionDenied),
  153. /*0x80030050*/ MAPHR(STG_E_FILEALREADYEXISTS, VBSERR_FileAlreadyExists),
  154. /*0x80030070*/ MAPHR(STG_E_MEDIUMFULL, VBSERR_DiskFull),
  155. /*0x800300FC*/ MAPHR(STG_E_INVALIDNAME, VBSERR_FileNotFound),
  156. /*0x80030100*/ MAPHR(STG_E_INUSE, VBSERR_PermissionDenied),
  157. /*0x80030101*/ MAPHR(STG_E_NOTCURRENT, VBSERR_PermissionDenied),
  158. /*0x80030103*/ MAPHR(STG_E_CANTSAVE, VBSERR_IOError),
  159. // FACILITY_ITF errors.
  160. /*0x80040154*/ MAPHR(REGDB_E_CLASSNOTREG, VBSERR_CantCreateObject),
  161. /*0x800401E3*/ MAPHR(MK_E_UNAVAILABLE, VBSERR_CantCreateObject),
  162. /*0x800401E6*/ MAPHR(MK_E_INVALIDEXTENSION, VBSERR_OLEFileNotFound),
  163. /*0x800401EA*/ MAPHR(MK_E_CANTOPENFILE, VBSERR_OLEFileNotFound),
  164. /*0x800401F3*/ MAPHR(CO_E_CLASSSTRING, VBSERR_CantCreateObject),
  165. /*0x800401F5*/ MAPHR(CO_E_APPNOTFOUND, VBSERR_CantCreateObject),
  166. /*0x800401FE*/ MAPHR(CO_E_APPDIDNTREG, VBSERR_CantCreateObject),
  167. #if _WIN32 || _WIN64
  168. // FACILITY_WIN32 errors
  169. /*0x80070005*/ MAPHR(E_ACCESSDENIED, VBSERR_PermissionDenied),
  170. /*0x8007000E*/ MAPHR(E_OUTOFMEMORY, VBSERR_OutOfMemory),
  171. /*0x80070057*/ MAPHR(E_INVALIDARG, VBSERR_IllegalFuncCall),
  172. /*0x800706BA*/ MAPHR(_HRESULT_TYPEDEF_(0x800706BA), VBSERR_ServerNotFound),
  173. // FACILITY_WINDOWS
  174. /*0x80080005*/ MAPHR(CO_E_SERVER_EXEC_FAILURE, VBSERR_CantCreateObject),
  175. #endif // _WIN32 || _WIN64
  176. };
  177. const long kcmhr = sizeof(g_rgmhr) / sizeof(g_rgmhr[0]);
  178. HRESULT MapHr(HRESULT hr, ErrorTypeEnum * errorTypeOut)
  179. {
  180. int imhrMin, imhrLim, imhr;
  181. #if DEBUG
  182. // In debug, check that all the entries in the error map table are
  183. // sorted based on the HRESULT in ascending order. We will then binary
  184. // search the sorted array. We need do this only once per invocation.
  185. static BOOL fCheckSort = TRUE;
  186. if (fCheckSort)
  187. {
  188. fCheckSort = FALSE;
  189. for (imhr = 1; imhr < kcmhr; imhr++)
  190. Assert((ulong)g_rgmhr[imhr - 1].hrIn < (ulong)g_rgmhr[imhr].hrIn);
  191. }
  192. #endif // DEBUG
  193. if (errorTypeOut != nullptr)
  194. {
  195. *errorTypeOut = kjstError;
  196. }
  197. if (SUCCEEDED(hr))
  198. return NOERROR;
  199. if (FACILITY_CONTROL == HRESULT_FACILITY(hr))
  200. return hr;
  201. for (imhrMin = 0, imhrLim = kcmhr; imhrMin < imhrLim; )
  202. {
  203. imhr = (imhrMin + imhrLim) / 2;
  204. if ((ulong)g_rgmhr[imhr].hrIn < (ulong)hr)
  205. imhrMin = imhr + 1;
  206. else
  207. imhrLim = imhr;
  208. }
  209. if (imhrMin < kcmhr && hr == g_rgmhr[imhrMin].hrIn)
  210. {
  211. if (errorTypeOut != nullptr)
  212. {
  213. *errorTypeOut = g_rgmhr[imhrMin].errorType;
  214. }
  215. return g_rgmhr[imhrMin].hrOut;
  216. }
  217. return hr;
  218. }
  219. // === ScriptException ===
  220. ScriptException::~ScriptException(void)
  221. {
  222. FreeExcepInfo(&ei);
  223. }
  224. void ScriptException::CopyInto(ScriptException *pse)
  225. {
  226. pse->ichMin = ichMin;
  227. pse->ichLim = ichLim;
  228. CopyException(&(pse->ei), &ei);
  229. }
  230. void ScriptException::Free(void)
  231. {
  232. ichMin = ichLim = 0;
  233. FreeExcepInfo(&ei);
  234. }
  235. void ScriptException::GetError(HRESULT *phr, EXCEPINFO *pei)
  236. {
  237. AssertMem(phr);
  238. AssertMemN(pei);
  239. if (HR(SCRIPT_E_RECORDED) == *phr)
  240. {
  241. Assert(FAILED(HR(ei.scode)));
  242. if (nullptr == pei)
  243. *phr = HR(ei.scode);
  244. else
  245. {
  246. *phr = HR(DISP_E_EXCEPTION);
  247. js_memcpy_s(pei, sizeof(*pei), &ei, sizeof(*pei));
  248. memset(&ei, 0, sizeof(ei));
  249. if (nullptr != pei->pfnDeferredFillIn)
  250. {
  251. pei->pfnDeferredFillIn(pei);
  252. pei->pfnDeferredFillIn = nullptr;
  253. }
  254. }
  255. }
  256. }
  257. // === CompileScriptException ===
  258. CompileScriptException::~CompileScriptException()
  259. {
  260. SysFreeString(bstrLine);
  261. }
  262. void CompileScriptException::Clear()
  263. {
  264. memset(this, 0, sizeof(*this));
  265. }
  266. void CompileScriptException::Free()
  267. {
  268. ScriptException::Free();
  269. line = ichMinLine = 0;
  270. if (nullptr != bstrLine)
  271. {
  272. SysFreeString(bstrLine);
  273. bstrLine = nullptr;
  274. }
  275. }
  276. HRESULT CompileScriptException::ProcessError(IScanner * pScan, HRESULT hr, ParseNode * pnodeBase)
  277. {
  278. if (nullptr == this)
  279. return hr;
  280. // fill in the ScriptException structure
  281. Clear();
  282. ei.scode = GetScode(MapHr(hr));
  283. // get the error string
  284. if (FACILITY_CONTROL != HRESULT_FACILITY(ei.scode) ||
  285. nullptr == (ei.bstrDescription =
  286. BstrGetResourceString(HRESULT_CODE(ei.scode))))
  287. {
  288. OLECHAR szT[50];
  289. _snwprintf_s(szT, ARRAYSIZE(szT), ARRAYSIZE(szT)-1, OLESTR("error %d"), ei.scode);
  290. if (nullptr == (ei.bstrDescription = SysAllocString(szT)))
  291. ei.scode = E_OUTOFMEMORY;
  292. }
  293. ei.bstrSource = BstrGetResourceString(IDS_COMPILATION_ERROR_SOURCE);
  294. if (nullptr == pnodeBase && nullptr != pScan)
  295. {
  296. // parsing phase - get the line number from the scanner
  297. AssertMem(pScan);
  298. this->hasLineNumberInfo = true;
  299. pScan->GetErrorLineInfo(this->ichMin, this->ichLim, this->line, this->ichMinLine);
  300. HRESULT hrSysAlloc = pScan->SysAllocErrorLine(this->ichMinLine, &this->bstrLine);
  301. if( FAILED(hrSysAlloc) )
  302. {
  303. return hrSysAlloc;
  304. }
  305. if (ichMin < ichMinLine)
  306. ichMin = ichMinLine;
  307. }
  308. else
  309. {
  310. // TODO: Variable length registers.
  311. // Remove E_FAIL once we have this feature.
  312. // error during code gen - no line number info available
  313. // E_ABORT may result if compilation does stack probe while thread is in disabled state.
  314. Assert(hr == JSERR_AsmJsCompileError || hr == ERRnoMemory || hr == VBSERR_OutOfStack || hr == E_OUTOFMEMORY || hr == E_FAIL || hr == E_ABORT);
  315. }
  316. return SCRIPT_E_RECORDED;
  317. }