- Add a dummy winspool.drv SpoolerInit doing an RPC call to a dummy RpcSpoolerInit...
[reactos.git] / reactos / win32ss / printing / base / spoolss / context.c
diff --git a/reactos/win32ss/printing/base/spoolss/context.c b/reactos/win32ss/printing/base/spoolss/context.c
new file mode 100644 (file)
index 0000000..5fce2bc
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * PROJECT:     ReactOS Spooler Router
+ * LICENSE:     GNU LGPL v2.1 or any later version as published by the Free Software Foundation
+ * PURPOSE:     Functions related to switching between security contexts
+ * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ */
+
+#include "precomp.h"
+
+/**
+ * @see RevertToPrinterSelf
+ */
+BOOL WINAPI
+ImpersonatePrinterClient(HANDLE hToken)
+{
+    if (!hToken)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!SetThreadToken(NULL, hToken))
+    {
+        ERR("SetThreadToken failed with error %u!\n", GetLastError());
+        CloseHandle(hToken);
+        return FALSE;
+    }
+
+    CloseHandle(hToken);
+    return TRUE;
+}
+
+/**
+ * RevertToPrinterSelf reverts the security context from the current user's context back to the process context.
+ * As spoolss.dll is used by spoolsv.exe, this is usually the SYSTEM security context.
+ *
+ * Unlike the traditional ImpersonateClient and then RevertToSelf approach, we do it the other way round here,
+ * because spoolss.dll is delay-loaded by spoolsv.exe in the current user's context. Use RevertToPrinterSelf then to
+ * return to the SYSTEM context for specific tasks.
+ */
+HANDLE WINAPI
+RevertToPrinterSelf()
+{
+    HANDLE hToken;
+
+    // Retrieve our current impersonation token
+    if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hToken))
+    {
+        ERR("OpenThreadToken failed with error %u!\n", GetLastError());
+        return NULL;
+    }
+
+    // Tell the thread to stop impersonating
+    if (!SetThreadToken(NULL, NULL))
+    {
+        ERR("SetThreadToken failed with error %u!\n", GetLastError());
+        return NULL;
+    }
+
+    // Return the token required for reverting back to impersonation in ImpersonatePrinterClient
+    return hToken;
+}