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.

251 lines
4.8 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. error.c
  5. Abstract:
  6. This module contains a routine for converting NT status codes
  7. to DOS/OS|2 error codes.
  8. Author:
  9. David Treadwell (davidtr) 04-Apr-1991
  10. Revision History:
  11. --*/
  12. #include <ntrtlp.h>
  13. #include "winerror.h"
  14. #include "error.h"
  15. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  16. #pragma alloc_text(PAGE, RtlGetLastNtStatus)
  17. #pragma alloc_text(PAGE, RtlGetLastWin32Error)
  18. #pragma alloc_text(PAGE, RtlNtStatusToDosError)
  19. #pragma alloc_text(PAGE, RtlRestoreLastWin32Error)
  20. #pragma alloc_text(PAGE, RtlSetLastWin32Error)
  21. #pragma alloc_text(PAGE, RtlSetLastWin32ErrorAndNtStatusFromNtStatus)
  22. #endif
  23. //
  24. // Ensure that the Registry ERROR_SUCCESS error code and the
  25. // NO_ERROR error code remain equal and zero.
  26. //
  27. #if ERROR_SUCCESS != 0 || NO_ERROR != 0
  28. #error Invalid value for ERROR_SUCCESS.
  29. #endif
  30. ULONG
  31. RtlNtStatusToDosError (
  32. IN NTSTATUS Status
  33. )
  34. /*++
  35. Routine Description:
  36. This routine converts an NT status code to its DOS/OS|2 equivalent.
  37. Remembers the Status code value in the TEB.
  38. Arguments:
  39. Status - Supplies the status value to convert.
  40. Return Value:
  41. The matching DOS/OS|2 error code.
  42. --*/
  43. {
  44. PTEB Teb;
  45. Teb = NtCurrentTeb();
  46. if (Teb) {
  47. try {
  48. Teb->LastStatusValue = Status;
  49. } except (EXCEPTION_EXECUTE_HANDLER) {
  50. }
  51. }
  52. return RtlNtStatusToDosErrorNoTeb( Status );
  53. }
  54. ULONG
  55. RtlNtStatusToDosErrorNoTeb (
  56. IN NTSTATUS Status
  57. )
  58. /*++
  59. Routine Description:
  60. This routine converts an NT status code to its DOS/OS 2 equivalent
  61. and returns the translated value.
  62. Arguments:
  63. Status - Supplies the status value to convert.
  64. Return Value:
  65. The matching DOS/OS 2 error code.
  66. --*/
  67. {
  68. ULONG Offset;
  69. ULONG Entry;
  70. ULONG Index;
  71. //
  72. // Convert any HRESULTs to their original form of a NTSTATUS or a
  73. // WIN32 error
  74. //
  75. if (Status & 0x20000000) {
  76. //
  77. // The customer bit is set so lets just pass the
  78. // error code on thru
  79. //
  80. return Status;
  81. }
  82. else if ((Status & 0xffff0000) == 0x80070000) {
  83. //
  84. // The status code was a win32 error already.
  85. //
  86. return(Status & 0x0000ffff);
  87. }
  88. else if ((Status & 0xf0000000) == 0xd0000000) {
  89. //
  90. // The status code is a HRESULT from NTSTATUS
  91. //
  92. Status &= 0xcfffffff;
  93. }
  94. //
  95. // Scan the run length table and compute the entry in the translation
  96. // table that maps the specified status code to a DOS error code.
  97. //
  98. Entry = 0;
  99. Index = 0;
  100. do {
  101. if ((ULONG)Status >= RtlpRunTable[Entry + 1].BaseCode) {
  102. Index += (RtlpRunTable[Entry].RunLength * RtlpRunTable[Entry].CodeSize);
  103. } else {
  104. Offset = (ULONG)Status - RtlpRunTable[Entry].BaseCode;
  105. if (Offset >= RtlpRunTable[Entry].RunLength) {
  106. break;
  107. } else {
  108. Index += (Offset * (ULONG)RtlpRunTable[Entry].CodeSize);
  109. if (RtlpRunTable[Entry].CodeSize == 1) {
  110. return (ULONG)RtlpStatusTable[Index];
  111. } else {
  112. return (((ULONG)RtlpStatusTable[Index + 1] << 16) |
  113. (ULONG)RtlpStatusTable[Index]);
  114. }
  115. }
  116. }
  117. Entry += 1;
  118. } while (Entry < (sizeof(RtlpRunTable) / sizeof(RUN_ENTRY)));
  119. //
  120. // The translation to a DOS error code failed.
  121. //
  122. // The redirector maps unknown OS/2 error codes by ORing 0xC001 into
  123. // the high 16 bits. Detect this and return the low 16 bits if true.
  124. //
  125. if (((ULONG)Status >> 16) == 0xC001) {
  126. return ((ULONG)Status & 0xFFFF);
  127. }
  128. #ifndef NTOS_KERNEL_RUNTIME
  129. DbgPrint("RTL: RtlNtStatusToDosError(0x%lx): No Valid Win32 Error Mapping\n",Status);
  130. DbgPrint("RTL: Edit ntos\\rtl\\generr.c to correct the problem\n");
  131. DbgPrint("RTL: ERROR_MR_MID_NOT_FOUND is being returned\n");
  132. #if DBG
  133. DbgBreakPoint();
  134. #endif // DBG
  135. #endif // NTOS_KERNEL_RUNTIME
  136. return ERROR_MR_MID_NOT_FOUND;
  137. }
  138. NTSTATUS
  139. NTAPI
  140. RtlGetLastNtStatus(
  141. VOID
  142. )
  143. {
  144. return NtCurrentTeb()->LastStatusValue;
  145. }
  146. LONG
  147. NTAPI
  148. RtlGetLastWin32Error(
  149. VOID
  150. )
  151. {
  152. return NtCurrentTeb()->LastErrorValue;
  153. }
  154. VOID
  155. NTAPI
  156. RtlSetLastWin32ErrorAndNtStatusFromNtStatus(
  157. NTSTATUS Status
  158. )
  159. {
  160. //
  161. // RtlNtStatusToDosError stores into NtCurrentTeb()->LastStatusValue.
  162. //
  163. RtlSetLastWin32Error(RtlNtStatusToDosError(Status));
  164. }
  165. VOID
  166. NTAPI
  167. RtlSetLastWin32Error(
  168. LONG Win32Error
  169. )
  170. {
  171. //
  172. // Arguably this should clear or reset the last nt status, but it does not
  173. // touch it.
  174. //
  175. NtCurrentTeb()->LastErrorValue = Win32Error;
  176. }
  177. VOID
  178. NTAPI
  179. RtlRestoreLastWin32Error(
  180. LONG Win32Error
  181. )
  182. {
  183. #if DBG
  184. if ((LONG)NtCurrentTeb()->LastErrorValue != Win32Error)
  185. #endif
  186. NtCurrentTeb()->LastErrorValue = Win32Error;
  187. }