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.

260 lines
5.2 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. if ((Status & 0x0fff0000) != ((FACILITY_MSMQ) << 16)){
  134. //
  135. // If this is MSMQ facility error, skip the assert
  136. //
  137. DbgBreakPoint();
  138. }
  139. #endif // DBG
  140. #endif // NTOS_KERNEL_RUNTIME
  141. return ERROR_MR_MID_NOT_FOUND;
  142. }
  143. NTSTATUS
  144. NTAPI
  145. RtlGetLastNtStatus(
  146. VOID
  147. )
  148. {
  149. return NtCurrentTeb()->LastStatusValue;
  150. }
  151. LONG
  152. NTAPI
  153. RtlGetLastWin32Error(
  154. VOID
  155. )
  156. {
  157. return NtCurrentTeb()->LastErrorValue;
  158. }
  159. VOID
  160. NTAPI
  161. RtlSetLastWin32ErrorAndNtStatusFromNtStatus(
  162. NTSTATUS Status
  163. )
  164. {
  165. //
  166. // RtlNtStatusToDosError stores into NtCurrentTeb()->LastStatusValue.
  167. //
  168. RtlSetLastWin32Error(RtlNtStatusToDosError(Status));
  169. }
  170. VOID
  171. NTAPI
  172. RtlSetLastWin32Error(
  173. LONG Win32Error
  174. )
  175. {
  176. //
  177. // Arguably this should clear or reset the last nt status, but it does not
  178. // touch it.
  179. //
  180. NtCurrentTeb()->LastErrorValue = Win32Error;
  181. }
  182. VOID
  183. NTAPI
  184. RtlRestoreLastWin32Error(
  185. LONG Win32Error
  186. )
  187. {
  188. #if DBG
  189. if ((LONG)NtCurrentTeb()->LastErrorValue != Win32Error)
  190. #endif
  191. NtCurrentTeb()->LastErrorValue = Win32Error;
  192. }