aboutsummaryrefslogtreecommitdiff
path: root/CRT/DriverThread.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'CRT/DriverThread.hpp')
-rw-r--r--CRT/DriverThread.hpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/CRT/DriverThread.hpp b/CRT/DriverThread.hpp
new file mode 100644
index 0000000..ac2eddd
--- /dev/null
+++ b/CRT/DriverThread.hpp
@@ -0,0 +1,167 @@
+#ifndef DDK_THREAD
+#define DDK_THREAD 1
+
+#include <ntddk.h>
+
+#include <EASTL/deque.h>
+#include <EASTL/functional.h>
+#include <EASTL/shared_ptr.h>
+
+extern "C" void InterceptorThreadRoutine(PVOID threadContext);
+
+namespace DriverThread
+{
+class Mutex
+{
+public:
+ Mutex(void);
+ ~Mutex(void);
+
+private:
+ void Lock();
+ void Unlock();
+
+ volatile long int m_interlock;
+
+ friend class LockGuard;
+};
+
+class LockGuard
+{
+public:
+ LockGuard(Mutex & m);
+ ~LockGuard(void);
+
+private:
+ Mutex m_Lock;
+};
+
+class ThreadArgs : public virtual eastl::enable_shared_from_this<ThreadArgs>
+{
+public:
+ ThreadArgs(void)
+ {
+ }
+ ThreadArgs(const ThreadArgs &) = delete;
+ virtual ~ThreadArgs(void)
+ {
+ }
+};
+
+using ThreadRoutine = eastl::function<NTSTATUS(eastl::shared_ptr<ThreadArgs> args)>;
+
+class Thread
+{
+public:
+ Thread(void);
+ Thread(const Thread &) = delete;
+ ~Thread(void);
+ NTSTATUS Start(ThreadRoutine routine, eastl::shared_ptr<ThreadArgs> args);
+ NTSTATUS WaitForTermination(LONGLONG timeout = 0);
+ HANDLE GetThreadId(void)
+ {
+ return m_threadId;
+ }
+ bool isRunning(void)
+ {
+ return GetThreadId() != nullptr;
+ }
+
+private:
+ friend void ::InterceptorThreadRoutine(PVOID threadContext);
+
+ HANDLE m_threadId = nullptr;
+ PETHREAD m_threadObject = nullptr;
+ Mutex m_mutex;
+ ThreadRoutine m_routine;
+ eastl::shared_ptr<ThreadArgs> m_threadContext;
+};
+
+class Spinlock
+{
+public:
+ Spinlock(void);
+ NTSTATUS Acquire(void);
+ void Release(void);
+ KIRQL GetOldIrql(void);
+
+private:
+ KIRQL m_oldIrql;
+ KSPIN_LOCK m_spinLock;
+};
+
+class Semaphore
+{
+public:
+ Semaphore(LONG initialValue = 0, LONG maxValue = MAXLONG);
+ NTSTATUS Wait(LONGLONG timeout = 0);
+ LONG Release(LONG adjustment = 1);
+
+private:
+ KSEMAPHORE m_semaphore;
+};
+
+class Event
+{
+public:
+ Event();
+ NTSTATUS Wait(LONGLONG timeout = 0);
+ NTSTATUS Notify();
+
+private:
+ KEVENT m_event;
+};
+
+class WorkItem final
+{
+ friend class WorkQueue;
+
+public:
+ WorkItem(const eastl::shared_ptr<void> & user) : m_user(std::move(user))
+ {
+ }
+ virtual ~WorkItem(void)
+ {
+ }
+ template <class T>
+ eastl::shared_ptr<T> Get(void)
+ {
+ return eastl::static_pointer_cast<T>(m_user);
+ }
+ template <class T>
+ void Get(eastl::shared_ptr<T> & dest)
+ {
+ dest = eastl::static_pointer_cast<T>(m_user);
+ }
+
+private:
+ eastl::shared_ptr<void> m_user;
+};
+
+using WorkerRoutine = eastl::function<NTSTATUS(WorkItem & item)>;
+
+class WorkQueue final
+{
+public:
+ WorkQueue(void);
+ WorkQueue(const WorkQueue &) = delete;
+ ~WorkQueue(void);
+ NTSTATUS Start(WorkerRoutine routine);
+ void Stop(bool wait = true);
+ void Enqueue(WorkItem & item);
+ void Enqueue(eastl::deque<WorkItem> & items);
+
+private:
+ Mutex m_mutex;
+ eastl::deque<WorkItem> m_queue;
+ Event m_wakeEvent;
+ bool m_stopWorker; // Work LIST must be empty and StopWorker TRUE to be able to stop!
+ Thread m_worker;
+ WorkerRoutine m_workerRoutine;
+
+ static NTSTATUS WorkerInterceptorRoutine(eastl::shared_ptr<ThreadArgs> args);
+};
+
+}; // namespace DriverThread
+
+#endif