summaryrefslogtreecommitdiffstats
path: root/win/rfb_win32/CurrentUser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win/rfb_win32/CurrentUser.cxx')
-rw-r--r--win/rfb_win32/CurrentUser.cxx152
1 files changed, 152 insertions, 0 deletions
diff --git a/win/rfb_win32/CurrentUser.cxx b/win/rfb_win32/CurrentUser.cxx
new file mode 100644
index 00000000..7562d29b
--- /dev/null
+++ b/win/rfb_win32/CurrentUser.cxx
@@ -0,0 +1,152 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that 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 software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- Currentuser.cxx
+
+#include <stdlib.h>
+#include <rfb/LogWriter.h>
+#include <rfb_win32/CurrentUser.h>
+#include <rfb_win32/DynamicFn.h>
+#include <rfb_win32/Service.h>
+#include <rfb_win32/OSVersion.h>
+#include <lmcons.h>
+
+using namespace rfb;
+using namespace win32;
+
+static LogWriter vlog("CurrentUser");
+
+
+const TCHAR* shellIconClass = _T("Shell_TrayWnd");
+
+BOOL CALLBACK enumWindows(HWND hwnd, LPARAM lParam) {
+ TCHAR className[16];
+ if (GetClassName(hwnd, className, sizeof(className)) &&
+ (_tcscmp(className, shellIconClass) == 0)) {
+ vlog.debug("located tray icon window (%s)", (const char*)CStr(className));
+ DWORD processId = 0;
+ GetWindowThreadProcessId(hwnd, &processId);
+ if (!processId)
+ return TRUE;
+ Handle process = OpenProcess(MAXIMUM_ALLOWED, FALSE, processId);
+ if (!process.h)
+ return TRUE;
+ if (!OpenProcessToken(process, MAXIMUM_ALLOWED, (HANDLE*)lParam))
+ return TRUE;
+ vlog.debug("obtained user token");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL CALLBACK enumDesktops(LPTSTR lpszDesktop, LPARAM lParam) {
+ HDESK desktop = OpenDesktop(lpszDesktop, 0, FALSE, DESKTOP_ENUMERATE);
+ vlog.debug("opening \"%s\"", lpszDesktop);
+ if (!desktop) {
+ vlog.info("desktop \"%s\" inaccessible", (const char*)CStr(lpszDesktop));
+ return TRUE;
+ }
+ BOOL result = EnumDesktopWindows(desktop, enumWindows, lParam);
+ if (!CloseDesktop(desktop))
+ vlog.info("unable to close desktop: %ld", GetLastError());
+ return result;
+}
+
+
+CurrentUserToken::CurrentUserToken() : isSafe_(false) {
+ if (isServiceProcess()) {
+ // If the platform is Windows 95/98/Me then we must fake the token's presence
+ if (osVersion.isPlatformWindows) {
+ try {
+ UserName un;
+ h = INVALID_HANDLE_VALUE;
+ } catch (rdr::SystemException& e) {
+ if (e.err != ERROR_NOT_LOGGED_ON)
+ throw;
+ if (FindWindow(shellIconClass, 0))
+ h = INVALID_HANDLE_VALUE;
+ }
+ isSafe_ = (h != 0);
+ return;
+ }
+
+ // Try to get the user token using the Terminal Services APIs
+ // NB: This will only work under XP/2003 and later
+ typedef BOOL (WINAPI *WTSQueryUserToken_proto)(ULONG, PHANDLE);
+ DynamicFn<WTSQueryUserToken_proto> _WTSQueryUserToken(_T("wtsapi32.dll"), "WTSQueryUserToken");
+ if (_WTSQueryUserToken.isValid()) {
+ (*_WTSQueryUserToken)(-1, &h);
+ isSafe_ = true;
+ return;
+ }
+
+ // Try to find the Shell Tray Icon window and take its token
+ // NB: This will only work under NT/2K (and later, but they're dealt with above)
+ // NB: If the shell is not running then this will return an Unsafe Null token.
+ EnumDesktops(GetProcessWindowStation(), enumDesktops, (LONG)&h);
+ isSafe_ = (h != 0);
+ } else {
+ // Try to open the security token for the User-Mode process
+ if (!OpenProcessToken(GetCurrentProcess(), GENERIC_ALL, &h)) {
+ DWORD err = GetLastError();
+ if (err != ERROR_CALL_NOT_IMPLEMENTED)
+ throw rdr::SystemException("OpenProcessToken failed", err);
+ // Under Windows 95/98/Me, we fake the handle value...
+ h = INVALID_HANDLE_VALUE;
+ }
+ isSafe_ = true;
+ }
+}
+
+
+ImpersonateCurrentUser::ImpersonateCurrentUser() {
+ RegCloseKey(HKEY_CURRENT_USER);
+ if (!isServiceProcess())
+ return;
+ if (!token.canImpersonate())
+ throw rdr::Exception("Cannot impersonate unsafe or null token");
+ if (!ImpersonateLoggedOnUser(token)) {
+ DWORD err = GetLastError();
+ if (err != ERROR_CALL_NOT_IMPLEMENTED)
+ throw rdr::SystemException("Failed to impersonate user", GetLastError());
+ }
+}
+
+ImpersonateCurrentUser::~ImpersonateCurrentUser() {
+ if (!RevertToSelf()) {
+ DWORD err = GetLastError();
+ if (err != ERROR_CALL_NOT_IMPLEMENTED)
+ exit(err);
+ }
+ RegCloseKey(HKEY_CURRENT_USER);
+}
+
+
+UserName::UserName() : TCharArray(UNLEN+1) {
+ DWORD len = UNLEN+1;
+ if (!GetUserName(buf, &len))
+ throw rdr::SystemException("GetUserName failed", GetLastError());
+}
+
+
+UserSID::UserSID() {
+ CurrentUserToken token;
+ if (!token.canImpersonate())
+ return;
+ setSID(Sid::FromToken(token.h));
+}