ErrorCodes.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*************************************************************************************
  2. Extended WPF Toolkit
  3. Copyright (C) 2007-2013 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
  6. For more features, controls, and fast professional support,
  7. pick up the Plus Edition at http://xceed.com/wpf_toolkit
  8. Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
  9. ***********************************************************************************/
  10. /**************************************************************************\
  11. Copyright Microsoft Corporation. All Rights Reserved.
  12. \**************************************************************************/
  13. namespace Standard
  14. {
  15. using System;
  16. using System.ComponentModel;
  17. using System.Diagnostics.CodeAnalysis;
  18. using System.Globalization;
  19. using System.Reflection;
  20. using System.Runtime.InteropServices;
  21. /// <summary>
  22. /// Wrapper for common Win32 status codes.
  23. /// </summary>
  24. [StructLayout(LayoutKind.Explicit)]
  25. internal struct Win32Error
  26. {
  27. [FieldOffset(0)]
  28. private readonly int _value;
  29. // NOTE: These public static field declarations are automatically
  30. // picked up by (HRESULT's) ToString through reflection.
  31. /// <summary>The operation completed successfully.</summary>
  32. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  33. public static readonly Win32Error ERROR_SUCCESS = new Win32Error(0);
  34. /// <summary>Incorrect function.</summary>
  35. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  36. public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error(1);
  37. /// <summary>The system cannot find the file specified.</summary>
  38. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  39. public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error(2);
  40. /// <summary>The system cannot find the path specified.</summary>
  41. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  42. public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error(3);
  43. /// <summary>The system cannot open the file.</summary>
  44. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  45. public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error(4);
  46. /// <summary>Access is denied.</summary>
  47. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  48. public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error(5);
  49. /// <summary>The handle is invalid.</summary>
  50. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  51. public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error(6);
  52. /// <summary>Not enough storage is available to complete this operation.</summary>
  53. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  54. public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error(14);
  55. /// <summary>There are no more files.</summary>
  56. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  57. public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error(18);
  58. /// <summary>The process cannot access the file because it is being used by another process.</summary>
  59. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  60. public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error(32);
  61. /// <summary>The parameter is incorrect.</summary>
  62. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  63. public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error(87);
  64. /// <summary>The data area passed to a system call is too small.</summary>
  65. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  66. public static readonly Win32Error ERROR_INSUFFICIENT_BUFFER = new Win32Error(122);
  67. /// <summary>Cannot nest calls to LoadModule.</summary>
  68. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  69. public static readonly Win32Error ERROR_NESTING_NOT_ALLOWED = new Win32Error(215);
  70. /// <summary>Illegal operation attempted on a registry key that has been marked for deletion.</summary>
  71. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  72. public static readonly Win32Error ERROR_KEY_DELETED = new Win32Error(1018);
  73. /// <summary>Element not found.</summary>
  74. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  75. public static readonly Win32Error ERROR_NOT_FOUND = new Win32Error(1168);
  76. /// <summary>There was no match for the specified key in the index.</summary>
  77. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  78. public static readonly Win32Error ERROR_NO_MATCH = new Win32Error(1169);
  79. /// <summary>An invalid device was specified.</summary>
  80. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  81. public static readonly Win32Error ERROR_BAD_DEVICE = new Win32Error(1200);
  82. /// <summary>The operation was canceled by the user.</summary>
  83. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  84. public static readonly Win32Error ERROR_CANCELLED = new Win32Error(1223);
  85. /// <summary>The window class was already registered.</summary>
  86. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  87. public static readonly Win32Error ERROR_CLASS_ALREADY_EXISTS = new Win32Error(1410);
  88. /// <summary>The specified datatype is invalid.</summary>
  89. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  90. public static readonly Win32Error ERROR_INVALID_DATATYPE = new Win32Error(1804);
  91. /// <summary>
  92. /// Create a new Win32 error.
  93. /// </summary>
  94. /// <param name="i">The integer value of the error.</param>
  95. public Win32Error(int i)
  96. {
  97. _value = i;
  98. }
  99. /// <summary>Performs HRESULT_FROM_WIN32 conversion.</summary>
  100. /// <param name="error">The Win32 error being converted to an HRESULT.</param>
  101. /// <returns>The equivilent HRESULT value.</returns>
  102. public static explicit operator HRESULT(Win32Error error)
  103. {
  104. // #define __HRESULT_FROM_WIN32(x)
  105. // ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
  106. if (error._value <= 0)
  107. {
  108. return new HRESULT((uint)error._value);
  109. }
  110. return HRESULT.Make(true, Facility.Win32, error._value & 0x0000FFFF);
  111. }
  112. // Method version of the cast operation
  113. /// <summary>Performs HRESULT_FROM_WIN32 conversion.</summary>
  114. /// <param name="error">The Win32 error being converted to an HRESULT.</param>
  115. /// <returns>The equivilent HRESULT value.</returns>
  116. public HRESULT ToHRESULT()
  117. {
  118. return (HRESULT)this;
  119. }
  120. /// <summary>Performs the equivalent of Win32's GetLastError()</summary>
  121. /// <returns>A Win32Error instance with the result of the native GetLastError</returns>
  122. [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
  123. public static Win32Error GetLastError()
  124. {
  125. return new Win32Error(Marshal.GetLastWin32Error());
  126. }
  127. public override bool Equals(object obj)
  128. {
  129. try
  130. {
  131. return ((Win32Error)obj)._value == _value;
  132. }
  133. catch (InvalidCastException)
  134. {
  135. return false;
  136. }
  137. }
  138. public override int GetHashCode()
  139. {
  140. return _value.GetHashCode();
  141. }
  142. /// <summary>
  143. /// Compare two Win32 error codes for equality.
  144. /// </summary>
  145. /// <param name="errLeft">The first error code to compare.</param>
  146. /// <param name="errRight">The second error code to compare.</param>
  147. /// <returns>Whether the two error codes are the same.</returns>
  148. public static bool operator ==(Win32Error errLeft, Win32Error errRight)
  149. {
  150. return errLeft._value == errRight._value;
  151. }
  152. /// <summary>
  153. /// Compare two Win32 error codes for inequality.
  154. /// </summary>
  155. /// <param name="errLeft">The first error code to compare.</param>
  156. /// <param name="errRight">The second error code to compare.</param>
  157. /// <returns>Whether the two error codes are not the same.</returns>
  158. public static bool operator !=(Win32Error errLeft, Win32Error errRight)
  159. {
  160. return !(errLeft == errRight);
  161. }
  162. }
  163. internal enum Facility
  164. {
  165. /// <summary>FACILITY_NULL</summary>
  166. Null = 0,
  167. /// <summary>FACILITY_RPC</summary>
  168. Rpc = 1,
  169. /// <summary>FACILITY_DISPATCH</summary>
  170. Dispatch = 2,
  171. /// <summary>FACILITY_STORAGE</summary>
  172. Storage = 3,
  173. /// <summary>FACILITY_ITF</summary>
  174. Itf = 4,
  175. /// <summary>FACILITY_WIN32</summary>
  176. Win32 = 7,
  177. /// <summary>FACILITY_WINDOWS</summary>
  178. Windows = 8,
  179. /// <summary>FACILITY_CONTROL</summary>
  180. Control = 10,
  181. /// <summary>MSDN doced facility code for ESE errors.</summary>
  182. Ese = 0xE5E,
  183. /// <summary>FACILITY_WINCODEC (WIC)</summary>
  184. WinCodec = 0x898,
  185. }
  186. /// <summary>Wrapper for HRESULT status codes.</summary>
  187. [StructLayout(LayoutKind.Explicit)]
  188. internal struct HRESULT
  189. {
  190. [FieldOffset(0)]
  191. private readonly uint _value;
  192. // NOTE: These public static field declarations are automatically
  193. // picked up by ToString through reflection.
  194. /// <summary>S_OK</summary>
  195. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  196. public static readonly HRESULT S_OK = new HRESULT(0x00000000);
  197. /// <summary>S_FALSE</summary>
  198. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  199. public static readonly HRESULT S_FALSE = new HRESULT(0x00000001);
  200. /// <summary>E_PENDING</summary>
  201. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  202. public static readonly HRESULT E_PENDING = new HRESULT(0x8000000A);
  203. /// <summary>E_NOTIMPL</summary>
  204. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  205. public static readonly HRESULT E_NOTIMPL = new HRESULT(0x80004001);
  206. /// <summary>E_NOINTERFACE</summary>
  207. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  208. public static readonly HRESULT E_NOINTERFACE = new HRESULT(0x80004002);
  209. /// <summary>E_POINTER</summary>
  210. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  211. public static readonly HRESULT E_POINTER = new HRESULT(0x80004003);
  212. /// <summary>E_ABORT</summary>
  213. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  214. public static readonly HRESULT E_ABORT = new HRESULT(0x80004004);
  215. /// <summary>E_FAIL</summary>
  216. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  217. public static readonly HRESULT E_FAIL = new HRESULT(0x80004005);
  218. /// <summary>E_UNEXPECTED</summary>
  219. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  220. public static readonly HRESULT E_UNEXPECTED = new HRESULT(0x8000FFFF);
  221. /// <summary>STG_E_INVALIDFUNCTION</summary>
  222. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  223. public static readonly HRESULT STG_E_INVALIDFUNCTION = new HRESULT(0x80030001);
  224. /// <summary>REGDB_E_CLASSNOTREG</summary>
  225. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  226. public static readonly HRESULT REGDB_E_CLASSNOTREG = new HRESULT(0x80040154);
  227. /// <summary>DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists.</summary>
  228. /// <remarks>There is no Assoc Handler for the given item registered by the specified application.</remarks>
  229. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  230. public static readonly HRESULT DESTS_E_NO_MATCHING_ASSOC_HANDLER = new HRESULT(0x80040F03);
  231. /// <summary>DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists.</summary>
  232. /// <remarks>The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration.</remarks>
  233. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  234. public static readonly HRESULT DESTS_E_NORECDOCS = new HRESULT(0x80040F04);
  235. /// <summary>DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists.</summary>
  236. /// <remarks>Not all of the items were successfully cleared</remarks>
  237. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  238. public static readonly HRESULT DESTS_E_NOTALLCLEARED = new HRESULT(0x80040F05);
  239. /// <summary>E_ACCESSDENIED</summary>
  240. /// <remarks>Win32Error ERROR_ACCESS_DENIED.</remarks>
  241. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  242. public static readonly HRESULT E_ACCESSDENIED = new HRESULT(0x80070005);
  243. /// <summary>E_OUTOFMEMORY</summary>
  244. /// <remarks>Win32Error ERROR_OUTOFMEMORY.</remarks>
  245. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  246. public static readonly HRESULT E_OUTOFMEMORY = new HRESULT(0x8007000E);
  247. /// <summary>E_INVALIDARG</summary>
  248. /// <remarks>Win32Error ERROR_INVALID_PARAMETER.</remarks>
  249. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  250. public static readonly HRESULT E_INVALIDARG = new HRESULT(0x80070057);
  251. /// <summary>INTSAFE_E_ARITHMETIC_OVERFLOW</summary>
  252. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  253. public static readonly HRESULT INTSAFE_E_ARITHMETIC_OVERFLOW = new HRESULT(0x80070216);
  254. /// <summary>COR_E_OBJECTDISPOSED</summary>
  255. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  256. public static readonly HRESULT COR_E_OBJECTDISPOSED = new HRESULT(0x80131622);
  257. /// <summary>WC_E_GREATERTHAN</summary>
  258. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  259. public static readonly HRESULT WC_E_GREATERTHAN = new HRESULT(0xC00CEE23);
  260. /// <summary>WC_E_SYNTAX</summary>
  261. [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
  262. public static readonly HRESULT WC_E_SYNTAX = new HRESULT(0xC00CEE2D);
  263. /// <summary>
  264. /// Create an HRESULT from an integer value.
  265. /// </summary>
  266. /// <param name="i"></param>
  267. public HRESULT(uint i)
  268. {
  269. _value = i;
  270. }
  271. public static HRESULT Make(bool severe, Facility facility, int code)
  272. {
  273. // #define MAKE_HRESULT(sev,fac,code) \
  274. // ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
  275. // Severity has 1 bit reserved.
  276. // bitness is enforced by the boolean parameter.
  277. // Facility has 11 bits reserved (different than SCODES, which have 4 bits reserved)
  278. // MSDN documentation incorrectly uses 12 bits for the ESE facility (e5e), so go ahead and let that one slide.
  279. // And WIC also ignores it the documented size...
  280. Assert.Implies((int)facility != (int)((int)facility & 0x1FF), facility == Facility.Ese || facility == Facility.WinCodec);
  281. // Code has 4 bits reserved.
  282. Assert.AreEqual(code, code & 0xFFFF);
  283. return new HRESULT((uint)((severe ? (1 << 31) : 0) | ((int)facility << 16) | code));
  284. }
  285. /// <summary>
  286. /// retrieve HRESULT_FACILITY
  287. /// </summary>
  288. public Facility Facility
  289. {
  290. get
  291. {
  292. return GetFacility((int)_value);
  293. }
  294. }
  295. public static Facility GetFacility(int errorCode)
  296. {
  297. // #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
  298. return (Facility)((errorCode >> 16) & 0x1fff);
  299. }
  300. /// <summary>
  301. /// retrieve HRESULT_CODE
  302. /// </summary>
  303. public int Code
  304. {
  305. get
  306. {
  307. return GetCode((int)_value);
  308. }
  309. }
  310. public static int GetCode(int error)
  311. {
  312. // #define HRESULT_CODE(hr) ((hr) & 0xFFFF)
  313. return (int)(error & 0xFFFF);
  314. }
  315. #region Object class override members
  316. /// <summary>
  317. /// Get a string representation of this HRESULT.
  318. /// </summary>
  319. /// <returns></returns>
  320. public override string ToString()
  321. {
  322. // Use reflection to try to name this HRESULT.
  323. // This is expensive, but if someone's ever printing HRESULT strings then
  324. // I think it's a fair guess that they're not in a performance critical area
  325. // (e.g. printing exception strings).
  326. // This is less error prone than trying to keep the list in the function.
  327. // To properly add an HRESULT's name to the ToString table, just add the HRESULT
  328. // like all the others above.
  329. //
  330. // CONSIDER: This data is static. It could be cached
  331. // after first usage for fast lookup since the keys are unique.
  332. //
  333. foreach (FieldInfo publicStaticField in typeof(HRESULT).GetFields(BindingFlags.Static | BindingFlags.Public))
  334. {
  335. if (publicStaticField.FieldType == typeof(HRESULT))
  336. {
  337. var hr = (HRESULT)publicStaticField.GetValue(null);
  338. if (hr == this)
  339. {
  340. return publicStaticField.Name;
  341. }
  342. }
  343. }
  344. // Try Win32 error codes also
  345. if (Facility == Facility.Win32)
  346. {
  347. foreach (FieldInfo publicStaticField in typeof(Win32Error).GetFields(BindingFlags.Static | BindingFlags.Public))
  348. {
  349. if (publicStaticField.FieldType == typeof(Win32Error))
  350. {
  351. var error = (Win32Error)publicStaticField.GetValue(null);
  352. if ((HRESULT)error == this)
  353. {
  354. return "HRESULT_FROM_WIN32(" + publicStaticField.Name + ")";
  355. }
  356. }
  357. }
  358. }
  359. // If there's no good name for this HRESULT,
  360. // return the string as readable hex (0x########) format.
  361. return string.Format(CultureInfo.InvariantCulture, "0x{0:X8}", _value);
  362. }
  363. public override bool Equals(object obj)
  364. {
  365. try
  366. {
  367. return ((HRESULT)obj)._value == _value;
  368. }
  369. catch (InvalidCastException)
  370. {
  371. return false;
  372. }
  373. }
  374. public override int GetHashCode()
  375. {
  376. return _value.GetHashCode();
  377. }
  378. #endregion
  379. public static bool operator ==(HRESULT hrLeft, HRESULT hrRight)
  380. {
  381. return hrLeft._value == hrRight._value;
  382. }
  383. public static bool operator !=(HRESULT hrLeft, HRESULT hrRight)
  384. {
  385. return !(hrLeft == hrRight);
  386. }
  387. public bool Succeeded
  388. {
  389. get { return (int)_value >= 0; }
  390. }
  391. public bool Failed
  392. {
  393. get { return (int)_value < 0; }
  394. }
  395. public void ThrowIfFailed()
  396. {
  397. ThrowIfFailed(null);
  398. }
  399. [
  400. SuppressMessage(
  401. "Microsoft.Usage",
  402. "CA2201:DoNotRaiseReservedExceptionTypes",
  403. Justification="Only recreating Exceptions that were already raised."),
  404. SuppressMessage(
  405. "Microsoft.Security",
  406. "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")
  407. ]
  408. public void ThrowIfFailed(string message)
  409. {
  410. if (Failed)
  411. {
  412. if (string.IsNullOrEmpty(message))
  413. {
  414. message = ToString();
  415. }
  416. #if DEBUG
  417. else
  418. {
  419. message += " (" + ToString() + ")";
  420. }
  421. #endif
  422. // Wow. Reflection in a throw call. Later on this may turn out to have been a bad idea.
  423. // If you're throwing an exception I assume it's OK for me to take some time to give it back.
  424. // I want to convert the HRESULT to a more appropriate exception type than COMException.
  425. // Marshal.ThrowExceptionForHR does this for me, but the general call uses GetErrorInfo
  426. // if it's set, and then ignores the HRESULT that I've provided. This makes it so this
  427. // call works the first time but you get burned on the second. To avoid this, I use
  428. // the overload that explicitly ignores the IErrorInfo.
  429. // In addition, the function doesn't allow me to set the Message unless I go through
  430. // the process of implementing an IErrorInfo and then use that. There's no stock
  431. // implementations of IErrorInfo available and I don't think it's worth the maintenance
  432. // overhead of doing it, nor would it have significant value over this approach.
  433. Exception e = Marshal.GetExceptionForHR((int)_value, new IntPtr(-1));
  434. Assert.IsNotNull(e);
  435. // ArgumentNullException doesn't have the right constructor parameters,
  436. // (nor does Win32Exception...)
  437. // but E_POINTER gets mapped to NullReferenceException,
  438. // so I don't think it will ever matter.
  439. Assert.IsFalse(e is ArgumentNullException);
  440. // If we're not getting anything better than a COMException from Marshal,
  441. // then at least check the facility and attempt to do better ourselves.
  442. if (e.GetType() == typeof(COMException))
  443. {
  444. switch (Facility)
  445. {
  446. case Facility.Win32:
  447. e = new Win32Exception(Code, message);
  448. break;
  449. default:
  450. e = new COMException(message, (int)_value);
  451. break;
  452. }
  453. }
  454. else
  455. {
  456. ConstructorInfo cons = e.GetType().GetConstructor(new[] { typeof(string) });
  457. if (null != cons)
  458. {
  459. e = cons.Invoke(new object[] { message }) as Exception;
  460. Assert.IsNotNull(e);
  461. }
  462. }
  463. throw e;
  464. }
  465. }
  466. /// <summary>
  467. /// Convert the result of Win32 GetLastError() into a raised exception.
  468. /// </summary>
  469. public static void ThrowLastError()
  470. {
  471. ((HRESULT)Win32Error.GetLastError()).ThrowIfFailed();
  472. // Only expecting to call this when we're expecting a failed GetLastError()
  473. Assert.Fail();
  474. }
  475. }
  476. }