diff --git a/libxenia.vcxproj b/libxenia.vcxproj
index 7cd83fb8f..84ac2ed3e 100644
--- a/libxenia.vcxproj
+++ b/libxenia.vcxproj
@@ -181,6 +181,7 @@
+
@@ -378,6 +379,7 @@
+
diff --git a/libxenia.vcxproj.filters b/libxenia.vcxproj.filters
index aa210d879..2fbe1ebcf 100644
--- a/libxenia.vcxproj.filters
+++ b/libxenia.vcxproj.filters
@@ -700,6 +700,9 @@
third_party\xxhash
+
+ src\xenia\kernel
+
@@ -1335,6 +1338,9 @@
third_party\xbyak\xbyak
+
+ src\xenia\kernel
+
diff --git a/src/xenia/kernel/xboxkrnl_error.cc b/src/xenia/kernel/xboxkrnl_error.cc
new file mode 100644
index 000000000..6458510b4
--- /dev/null
+++ b/src/xenia/kernel/xboxkrnl_error.cc
@@ -0,0 +1,62 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project *
+ ******************************************************************************
+ * Copyright 2013 Ben Vanik. All rights reserved. *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#include "xenia/kernel/xboxkrnl_error.h"
+
+#include
+
+#include "xenia/base/atomic.h"
+#include "xenia/base/logging.h"
+#include "xenia/base/string.h"
+#include "xenia/kernel/kernel_state.h"
+#include "xenia/kernel/xboxkrnl_private.h"
+#include "xenia/kernel/objects/xthread.h"
+#include "xenia/kernel/objects/xuser_module.h"
+#include "xenia/kernel/util/shim_utils.h"
+#include "xenia/kernel/util/xex2.h"
+
+namespace xe {
+namespace kernel {
+
+SHIM_CALL RtlNtStatusToDosError_shim(PPCContext* ppc_state,
+ KernelState* state) {
+ uint32_t status = SHIM_GET_ARG_32(0);
+
+ XELOGD("RtlNtStatusToDosError(%.4X)", status);
+
+ if (!status || (status & 0x20000000)) {
+ SHIM_SET_RETURN_32(status);
+ return;
+ }
+
+ if ((status >> 16) == 0x8007) {
+ SHIM_SET_RETURN_32(status & 0xFFFF);
+ return;
+ }
+
+ if ((status & 0xF0000000) == 0xD0000000) {
+ // High bits doesn't matter.
+ status &= ~0x30000000;
+ }
+
+ // TODO(benvanik): implement lookup table.
+ XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED");
+
+ uint32_t result = 317; // ERROR_MR_MID_NOT_FOUND
+
+ SHIM_SET_RETURN_32(result);
+}
+
+} // namespace kernel
+} // namespace xe
+
+void xe::kernel::xboxkrnl::RegisterErrorExports(
+ xe::cpu::ExportResolver* export_resolver, KernelState* state) {
+ SHIM_SET_MAPPING("xboxkrnl.exe", RtlNtStatusToDosError, state);
+}
diff --git a/src/xenia/kernel/xboxkrnl_error.h b/src/xenia/kernel/xboxkrnl_error.h
new file mode 100644
index 000000000..c76a569b4
--- /dev/null
+++ b/src/xenia/kernel/xboxkrnl_error.h
@@ -0,0 +1,21 @@
+/**
+ ******************************************************************************
+ * Xenia : Xbox 360 Emulator Research Project *
+ ******************************************************************************
+ * Copyright 2013 Ben Vanik. All rights reserved. *
+ * Released under the BSD license - see LICENSE in the root for more details. *
+ ******************************************************************************
+ */
+
+#ifndef XENIA_KERNEL_XBOXKRNL_ERROR_H_
+#define XENIA_KERNEL_XBOXKRNL_ERROR_H_
+
+#include "xenia/xbox.h"
+
+namespace xe {
+namespace kernel {
+
+} // namespace kernel
+} // namespace xe
+
+#endif // XENIA_KERNEL_XBOXKRNL_ERROR_H_
diff --git a/src/xenia/kernel/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl_module.cc
index 6ed43924e..7ff0aa65f 100644
--- a/src/xenia/kernel/xboxkrnl_module.cc
+++ b/src/xenia/kernel/xboxkrnl_module.cc
@@ -40,6 +40,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
xboxkrnl::RegisterModuleExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterObExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterRtlExports(export_resolver_, kernel_state_);
+ xboxkrnl::RegisterErrorExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterStringExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterThreadingExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterUsbcamExports(export_resolver_, kernel_state_);
diff --git a/src/xenia/kernel/xboxkrnl_private.h b/src/xenia/kernel/xboxkrnl_private.h
index a90c69974..56597f72b 100644
--- a/src/xenia/kernel/xboxkrnl_private.h
+++ b/src/xenia/kernel/xboxkrnl_private.h
@@ -25,6 +25,8 @@ void RegisterAudioXmaExports(xe::cpu::ExportResolver* export_resolver,
KernelState* state);
void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver,
KernelState* state);
+void RegisterErrorExports(xe::cpu::ExportResolver* export_resolver,
+ KernelState* state);
void RegisterHalExports(xe::cpu::ExportResolver* export_resolver,
KernelState* state);
void RegisterIoExports(xe::cpu::ExportResolver* export_resolver,
diff --git a/src/xenia/kernel/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl_rtl.cc
index 9f11db91e..a10c51e11 100644
--- a/src/xenia/kernel/xboxkrnl_rtl.cc
+++ b/src/xenia/kernel/xboxkrnl_rtl.cc
@@ -372,29 +372,6 @@ SHIM_CALL RtlUnicodeToMultiByteN_shim(PPCContext* ppc_state,
SHIM_SET_RETURN_32(0);
}
-SHIM_CALL RtlNtStatusToDosError_shim(PPCContext* ppc_state,
- KernelState* state) {
- uint32_t status = SHIM_GET_ARG_32(0);
-
- XELOGD("RtlNtStatusToDosError(%.4X)", status);
-
- if (!status || (status & 0x20000000)) {
- // Success.
- SHIM_SET_RETURN_32(0);
- return;
- } else if ((status & 0xF0000000) == 0xD0000000) {
- // High bit doesn't matter.
- status &= ~0x10000000;
- }
-
- // TODO(benvanik): implement lookup table.
- XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED");
-
- uint32_t result = 317; // ERROR_MR_MID_NOT_FOUND
-
- SHIM_SET_RETURN_32(result);
-}
-
SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t xex_header_base = SHIM_GET_ARG_32(0);
@@ -705,8 +682,6 @@ void xe::kernel::xboxkrnl::RegisterRtlExports(
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeToTimeFields, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlTimeFieldsToTime, state);
- SHIM_SET_MAPPING("xboxkrnl.exe", RtlNtStatusToDosError, state);
-
SHIM_SET_MAPPING("xboxkrnl.exe", RtlImageXexHeaderField, state);
SHIM_SET_MAPPING("xboxkrnl.exe", RtlInitializeCriticalSection, state);