diff --git a/include/stratosphere.hpp b/include/stratosphere.hpp
index b9141543..688d452d 100644
--- a/include/stratosphere.hpp
+++ b/include/stratosphere.hpp
@@ -16,6 +16,8 @@
#pragma once
+#include "stratosphere/defines.hpp"
+
#include "stratosphere/utilities.hpp"
#include "stratosphere/emummc_utilities.hpp"
@@ -23,6 +25,7 @@
#include "stratosphere/version_check.hpp"
+#include "stratosphere/auto_handle.hpp"
#include "stratosphere/hossynch.hpp"
#include "stratosphere/message_queue.hpp"
#include "stratosphere/iwaitable.hpp"
diff --git a/include/stratosphere/auto_handle.hpp b/include/stratosphere/auto_handle.hpp
new file mode 100644
index 00000000..77846547
--- /dev/null
+++ b/include/stratosphere/auto_handle.hpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include
+#include "defines.hpp"
+
+class AutoHandle {
+ NON_COPYABLE(AutoHandle);
+ private:
+ Handle hnd;
+ public:
+ AutoHandle() : hnd(INVALID_HANDLE) { /* ... */ }
+ AutoHandle(Handle h) : hnd(h) { /* ... */ }
+ ~AutoHandle() {
+ if (this->hnd != INVALID_HANDLE) {
+ svcCloseHandle(this->hnd);
+ this->hnd = INVALID_HANDLE;
+ }
+ }
+
+ AutoHandle(AutoHandle&& rhs) {
+ this->hnd = rhs.hnd;
+ rhs.hnd = INVALID_HANDLE;
+ }
+
+ AutoHandle& operator=(AutoHandle&& rhs) {
+ rhs.Swap(*this);
+ return *this;
+ }
+
+ explicit operator bool() const {
+ return this->hnd != INVALID_HANDLE;
+ }
+
+ void Swap(AutoHandle& rhs) {
+ std::swap(this->hnd, rhs.hnd);
+ }
+
+ Handle Get() const {
+ return this->hnd;
+ }
+
+ Handle *GetPointer() {
+ return &this->hnd;
+ }
+
+ Handle *GetPointerAndClear() {
+ this->Clear();
+ return this->GetPointer();
+ }
+
+ Handle Move() {
+ const Handle h = this->hnd;
+ this->hnd = INVALID_HANDLE;
+ return h;
+ }
+
+ void Reset(Handle h) {
+ AutoHandle(h).Swap(*this);
+ }
+
+ void Clear() {
+ this->Reset(INVALID_HANDLE);
+ }
+};
diff --git a/include/stratosphere/defines.hpp b/include/stratosphere/defines.hpp
new file mode 100644
index 00000000..2a76f02a
--- /dev/null
+++ b/include/stratosphere/defines.hpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+/* Any broadly useful language defines should go here. */
+
+#define NON_COPYABLE(cls) \
+ cls(const cls&) = delete; \
+ cls& operator=(const cls&) = delete
+
+#define NON_MOVEABLE(cls) \
+ cls(cls&&) = delete; \
+ cls& operator=(cls&&) = delete
diff --git a/include/stratosphere/hossynch.hpp b/include/stratosphere/hossynch.hpp
index 242f882b..624dba80 100644
--- a/include/stratosphere/hossynch.hpp
+++ b/include/stratosphere/hossynch.hpp
@@ -19,6 +19,7 @@
#include
#include
#include "results.hpp"
+#include "auto_handle.hpp"
class HosMutex {
private: