DeviceFrameBuffer.cxx
Dialog.cxx
DIBSectionBuffer.cxx
- DynamicFn.cxx
EventManager.cxx
LaunchProcess.cxx
ListViewControl.cxx
MonitorInfo.cxx
MsgWindow.cxx
- OSVersion.cxx
RegConfig.cxx
Registry.cxx
SecurityPage.cxx
add_library(rfb_win32 STATIC ${RFB_WIN32_SOURCES})
-target_link_libraries(rfb_win32 user32.lib comctl32.lib version.lib)
+target_link_libraries(rfb_win32 user32.lib comctl32.lib wtsapi32.lib version.lib)
#include <rfb_win32/CleanDesktop.h>
#include <rfb_win32/CurrentUser.h>
#include <rfb_win32/Registry.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb/LogWriter.h>
#include <rdr/Exception.h>
#include <os/os.h>
#include <set>
-#ifdef SPI_GETUIEFFECTS
-#define RFB_HAVE_SPI_UIEFFECTS
-#else
-#pragma message(" NOTE: Not building Get/Set UI Effects support.")
-#endif
-
using namespace rfb;
using namespace rfb::win32;
}
-CleanDesktop::CleanDesktop() : restoreActiveDesktop(false), restoreWallpaper(false),
- restorePattern(false), restoreEffects(false) {
+CleanDesktop::CleanDesktop() : restoreActiveDesktop(false),
+ restoreWallpaper(false),
+ restoreEffects(false) {
CoInitialize(0);
}
CleanDesktop::~CleanDesktop() {
enableEffects();
- enablePattern();
enableWallpaper();
CoUninitialize();
}
}
-void CleanDesktop::disablePattern() {
- try {
- ImpersonateCurrentUser icu;
-
- vlog.debug("disable desktop pattern");
- SysParamsInfo(SPI_SETDESKPATTERN, 0, (PVOID) "", SPIF_SENDCHANGE);
- restorePattern = true;
-
- } catch (rdr::Exception& e) {
- vlog.info("%s", e.str());
- }
-}
-
-void CleanDesktop::enablePattern() {
- try {
- if (restorePattern) {
- ImpersonateCurrentUser icu;
-
- vlog.debug("restoring pattern...");
-
- TCharArray pattern;
- if (osVersion.isPlatformWindows) {
- RegKey cfgKey;
- cfgKey.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
- pattern.buf = cfgKey.getString(_T("Pattern"));
- }
- SysParamsInfo(SPI_SETDESKPATTERN, 0, pattern.buf, SPIF_SENDCHANGE);
- restorePattern = false;
- }
-
- } catch (rdr::Exception& e) {
- vlog.info("%s", e.str());
- }
-}
-
-
void CleanDesktop::disableEffects() {
try {
ImpersonateCurrentUser icu;
vlog.debug("disable desktop effects");
SysParamsInfo(SPI_SETFONTSMOOTHING, FALSE, 0, SPIF_SENDCHANGE);
-#ifdef RFB_HAVE_SPI_UIEFFECTS
if (SysParamsInfo(SPI_GETUIEFFECTS, 0, &uiEffects, 0) == ERROR_CALL_NOT_IMPLEMENTED) {
SysParamsInfo(SPI_GETCOMBOBOXANIMATION, 0, &comboBoxAnim, 0);
SysParamsInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradientCaptions, 0);
// We *always* restore UI effects overall, since there is no Windows GUI to do it
uiEffects = TRUE;
}
-#else
- vlog.debug(" not supported");
-#endif
restoreEffects = true;
} catch (rdr::Exception& e) {
RegKey desktopCfg;
desktopCfg.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
SysParamsInfo(SPI_SETFONTSMOOTHING, desktopCfg.getInt(_T("FontSmoothing"), 0) != 0, 0, SPIF_SENDCHANGE);
-#ifdef RFB_HAVE_SPI_UIEFFECTS
if (SysParamsInfo(SPI_SETUIEFFECTS, 0, (void*)(intptr_t)uiEffects, SPIF_SENDCHANGE) == ERROR_CALL_NOT_IMPLEMENTED) {
SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, (void*)(intptr_t)comboBoxAnim, SPIF_SENDCHANGE);
SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, (void*)(intptr_t)gradientCaptions, SPIF_SENDCHANGE);
SysParamsInfo(SPI_SETMENUANIMATION, 0, (void*)(intptr_t)menuAnim, SPIF_SENDCHANGE);
}
restoreEffects = false;
-#else
- vlog.info(" not supported");
-#endif
}
} catch (rdr::Exception& e) {
#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>
+#include <wtsapi32.h>
using namespace rfb;
using namespace win32;
}
-CurrentUserToken::CurrentUserToken() : isSafe_(false) {
+CurrentUserToken::CurrentUserToken() {
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, (LPARAM)&h);
- isSafe_ = (h != 0);
+ WTSQueryUserToken(-1, &h);
} 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;
}
}
// for the currently logged-on user, or null if no user is
// logged on.
//
- // Under Windows 95/98/Me, which don't support security tokens,
- // the token will be INVALID_HANDLE_VALUE if a user is logged on.
- //
- // Under Windows NT/2K, it may be the case that the token is
- // null even when a user *is* logged on, because we use some hacks
- // to detect the user's token and sometimes they fail. On these
- // platforms, isSafe() will return False if the token is null.
- //
- // Under Windows XP, etc, isSafe() will always be True, and the token
- // will always be set to the currently logged on user's token.
- //
// canImpersonate() tests whether there is a user token that is safe
// to impersonate.
//
struct CurrentUserToken : public Handle {
CurrentUserToken();
- bool isSafe() const { return isSafe_; };
- bool canImpersonate() const { return h && isSafe(); }
- bool noUserLoggedOn() const { return !h && isSafe(); }
- private:
- bool isSafe_;
+ bool canImpersonate() const { return h; }
+ bool noUserLoggedOn() const { return !h; }
};
// ImpersonateCurrentUser
// Throws an exception on failure.
// Succeeds (trivially) if process is not running as service.
// Fails if CurrentUserToken is not valid.
- // Fails if platform is NT AND cannot impersonate token.
+ // Fails if cannot impersonate token.
// Succeeds otherwise.
struct ImpersonateCurrentUser {
// UserName
// Returns the name of the user the thread is currently running as.
// Raises a SystemException in case of error.
- // NB: Raises a SystemException with err == ERROR_NOT_LOGGED_ON if
- // running under Windows 9x/95/Me and no user is logged on.
struct UserName : public TCharArray {
UserName();
#include <vector>
#include <rfb_win32/DeviceFrameBuffer.h>
#include <rfb_win32/DeviceContext.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb_win32/IconInfo.h>
#include <rfb/VNCServer.h>
#include <rfb/LogWriter.h>
// Map the rectangle coords from VNC Desktop-relative to device relative - usually (0,0)
Point src = desktopToDevice(rect.tl);
- // Note: Microsoft's documentation lies directly about CAPTUREBLT and claims it works on 98/ME
- // If you try CAPTUREBLT on 98 then you get blank output...
- if (!::BitBlt(tmpDC, rect.tl.x, rect.tl.y, rect.width(), rect.height(), device, src.x, src.y,
- (osVersion.isPlatformNT && useCaptureBlt) ? (CAPTUREBLT | SRCCOPY) : SRCCOPY)) {
+ if (!::BitBlt(tmpDC, rect.tl.x, rect.tl.y,
+ rect.width(), rect.height(), device, src.x, src.y,
+ useCaptureBlt ? (CAPTUREBLT | SRCCOPY) : SRCCOPY)) {
if (ignoreGrabErrors)
vlog.error("BitBlt failed:%ld", GetLastError());
else
+++ /dev/null
-/* 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.
- */
-
-#include <rfb_win32/DynamicFn.h>
-#include <rfb_win32/TCharArray.h>
-#include <rfb/LogWriter.h>
-
-using namespace rfb;
-using namespace win32;
-
-static LogWriter vlog("DynamicFn");
-
-
-DynamicFnBase::DynamicFnBase(const TCHAR* dllName, const char* fnName) : fnPtr(0), dllHandle(0) {
- dllHandle = LoadLibrary(dllName);
- if (!dllHandle) {
- vlog.info("DLL %s not found (%lu)", (const char*)CStr(dllName), GetLastError());
- return;
- }
- fnPtr = (void*) GetProcAddress(dllHandle, fnName);
- if (!fnPtr)
- vlog.info("proc %s not found in %s (%lu)", fnName, (const char*)CStr(dllName), GetLastError());
-}
-
-DynamicFnBase::~DynamicFnBase() {
- if (dllHandle)
- FreeLibrary(dllHandle);
-}
-
-
+++ /dev/null
-/* 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.
- */
-
-// Helper class managing dynamic linkage to DLL functions.
-
-#ifndef __RFB_WIN32_DYNAMICFN_H__
-#define __RFB_WIN32_DYNAMICFN_H__
-
-#include <windows.h>
-
-namespace rfb {
- namespace win32 {
-
- class DynamicFnBase {
- public:
- DynamicFnBase(const TCHAR* dllName, const char* fnName);
- ~DynamicFnBase();
- bool isValid() const {return fnPtr != 0;}
- protected:
- void* fnPtr;
- HMODULE dllHandle;
- private:
- DynamicFnBase(const DynamicFnBase&);
- DynamicFnBase operator=(const DynamicFnBase&);
- };
-
- template<class T> class DynamicFn : public DynamicFnBase {
- public:
- DynamicFn(const TCHAR* dllName, const char* fnName) : DynamicFnBase(dllName, fnName) {}
- T operator *() const {return (T)fnPtr;};
- };
-
- };
-};
-
-#endif
* USA.
*/
-#include <rfb_win32/DynamicFn.h>
+#include <tchar.h>
#include <rfb_win32/MonitorInfo.h>
#include <rfb_win32/Win32Util.h>
#include <rdr/Exception.h>
static LogWriter vlog("MonitorInfo");
-// If we are building in multi-monitor support (i.e. the headers support it)
-// then do dynamic imports of the required system calls, and provide any
-// other code that wouldn't otherwise compile.
-#ifdef RFB_HAVE_MONITORINFO
-#include <tchar.h>
-typedef HMONITOR (WINAPI *_MonitorFromWindow_proto)(HWND,DWORD);
-static rfb::win32::DynamicFn<_MonitorFromWindow_proto> _MonitorFromWindow(_T("user32.dll"), "MonitorFromWindow");
-typedef HMONITOR (WINAPI *_MonitorFromRect_proto)(LPCRECT,DWORD);
-static rfb::win32::DynamicFn<_MonitorFromRect_proto> _MonitorFromRect(_T("user32.dll"), "MonitorFromRect");
-typedef BOOL (WINAPI *_GetMonitorInfo_proto)(HMONITOR,LPMONITORINFO);
-static rfb::win32::DynamicFn<_GetMonitorInfo_proto> _GetMonitorInfo(_T("user32.dll"), "GetMonitorInfoA");
-typedef BOOL (WINAPI *_EnumDisplayMonitors_proto)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
-static rfb::win32::DynamicFn<_EnumDisplayMonitors_proto> _EnumDisplayMonitors(_T("user32.dll"), "EnumDisplayMonitors");
static void fillMonitorInfo(HMONITOR monitor, MonitorInfo* mi) {
vlog.debug("monitor=%p", monitor);
- if (!_GetMonitorInfo.isValid())
- throw rdr::Exception("no GetMonitorInfo");
memset(mi, 0, sizeof(MONITORINFOEXA));
mi->cbSize = sizeof(MONITORINFOEXA);
- if (!(*_GetMonitorInfo)(monitor, mi))
+ if (!GetMonitorInfo(monitor, mi))
throw rdr::SystemException("failed to GetMonitorInfo", GetLastError());
vlog.debug("monitor is %ld,%ld-%ld,%ld", mi->rcMonitor.left, mi->rcMonitor.top, mi->rcMonitor.right, mi->rcMonitor.bottom);
vlog.debug("work area is %ld,%ld-%ld,%ld", mi->rcWork.left, mi->rcWork.top, mi->rcWork.right, mi->rcWork.bottom);
vlog.debug("device is \"%s\"", mi->szDevice);
}
-#else
-#pragma message(" NOTE: Not building Multi-Monitor support.")
-#endif
MonitorInfo::MonitorInfo(HWND window) {
cbSize = sizeof(MonitorInfo);
szDevice[0] = 0;
-#ifdef RFB_HAVE_MONITORINFO
- try {
- if (_MonitorFromWindow.isValid()) {
- HMONITOR monitor = (*_MonitorFromWindow)(window, MONITOR_DEFAULTTONEAREST);
- if (!monitor)
- throw rdr::SystemException("failed to get monitor", GetLastError());
- fillMonitorInfo(monitor, this);
- return;
- }
- } catch (rdr::Exception& e) {
- vlog.error("%s", e.str());
- }
-#endif
-
- // Legacy fallbacks - just return the desktop settings
- vlog.debug("using legacy fall-backs");
- HWND desktop = GetDesktopWindow();
- GetWindowRect(desktop, &rcMonitor);
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
- dwFlags = 0;
+ HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
+ if (!monitor)
+ throw rdr::SystemException("failed to get monitor", GetLastError());
+ fillMonitorInfo(monitor, this);
}
MonitorInfo::MonitorInfo(const RECT& r) {
cbSize = sizeof(MonitorInfo);
szDevice[0] = 0;
-#ifdef RFB_HAVE_MONITORINFO
- try {
- if (_MonitorFromRect.isValid()) {
- HMONITOR monitor = (*_MonitorFromRect)(&r, MONITOR_DEFAULTTONEAREST);
- if (!monitor)
- throw rdr::SystemException("failed to get monitor", GetLastError());
- fillMonitorInfo(monitor, this);
- return;
- }
- } catch (rdr::Exception& e) {
- vlog.error("%s", e.str());
- }
-#endif
-
- // Legacy fallbacks - just return the desktop settings
- vlog.debug("using legacy fall-backs");
- HWND desktop = GetDesktopWindow();
- GetWindowRect(desktop, &rcMonitor);
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
- dwFlags = 0;
+ HMONITOR monitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
+ if (!monitor)
+ throw rdr::SystemException("failed to get monitor", GetLastError());
+ fillMonitorInfo(monitor, this);
}
-#ifdef RFB_HAVE_MONITORINFO
-
struct monitorByNameData {
MonitorInfo* info;
const char* monitorName;
monitorByNameData* data = (monitorByNameData*)d;
memset(data->info, 0, sizeof(MONITORINFOEXA));
data->info->cbSize = sizeof(MONITORINFOEXA);
- if ((*_GetMonitorInfo)(monitor, data->info)) {
+ if (GetMonitorInfo(monitor, data->info)) {
if (stricmp(data->monitorName, data->info->szDevice) == 0)
return FALSE;
}
return TRUE;
}
-#endif
-
MonitorInfo::MonitorInfo(const char* devName) {
-#ifdef RFB_HAVE_MONITORINFO
- if (!_EnumDisplayMonitors.isValid()) {
- vlog.debug("EnumDisplayMonitors not found");
- } else {
- monitorByNameData data;
- data.info = this;
- data.monitorName = devName;
-
- (*_EnumDisplayMonitors)(0, 0, &monitorByNameEnumProc, (LPARAM)&data);
- if (stricmp(data.monitorName, szDevice) == 0)
- return;
- }
-#endif
- // If multi-monitor is not built, or not supported by the OS,
- // or if the named monitor is not found, revert to the primary monitor.
- vlog.debug("reverting to primary monitor");
- cbSize = sizeof(MonitorInfo);
- szDevice[0] = 0;
-
- HWND desktop = GetDesktopWindow();
- GetWindowRect(desktop, &rcMonitor);
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
- dwFlags = 0;
+ monitorByNameData data;
+ data.info = this;
+ data.monitorName = devName;
+ EnumDisplayMonitors(0, 0, &monitorByNameEnumProc, (LPARAM)&data);
}
void MonitorInfo::moveTo(HWND handle) {
vlog.debug("moveTo monitor=%s", szDevice);
-#ifdef RFB_HAVE_MONITORINFO
MonitorInfo mi(handle);
if (strcmp(szDevice, mi.szDevice) != 0) {
centerWindow(handle, rcWork);
clipTo(handle);
}
-#endif
}
void MonitorInfo::clipTo(RECT* r) {
*/
// Helper class used to obtain information about a particular monitor.
-// This class wraps the Windows MONITORINFOEX ASCII structure, providing
-// methods that can safely be called on both multi-monitor aware systems
-// and older "legacy" systems.
#ifndef __RFB_WIN32_MONITORINFO_H__
#define __RFB_WIN32_MONITORINFO_H__
#include <windows.h>
-#ifdef MONITOR_DEFAULTTONULL
-#define RFB_HAVE_MONITORINFO
-#endif
namespace rfb {
namespace win32 {
// Structure containing info on the monitor nearest the window.
- // Copes with multi-monitor OSes and older ones.
-#ifdef RFB_HAVE_MONITORINFO
struct MonitorInfo : MONITORINFOEXA {
-#else
- struct MonitorInfo {
- DWORD cbSize;
- RECT rcMonitor;
- RECT rcWork;
- DWORD dwFlags;
- char szDevice[1]; // Always null...
-#endif
-
// Constructor: Obtains monitor info for the monitor that has the
// greatest overlap with the supplied window or rectangle.
MonitorInfo(HWND hwnd);
+++ /dev/null
-/* 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.
- */
-
-// -=- OSVersion.cxx
-
-#include <rfb_win32/OSVersion.h>
-#include <rdr/Exception.h>
-#include <tchar.h>
-
-using namespace rfb;
-using namespace win32;
-
-
-OSVersionInfo::OSVersionInfo() {
- // Get OS Version Info
- ZeroMemory(static_cast<OSVERSIONINFO*>(this), sizeof(this));
- dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx(this))
- throw rdr::SystemException("unable to get system version info", GetLastError());
-
- // Set the special extra flags
- isPlatformNT = dwPlatformId == VER_PLATFORM_WIN32_NT;
- isPlatformWindows = dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;
-
- cannotSwitchDesktop = isPlatformNT && (dwMajorVersion==4) &&
- ((_tcscmp(szCSDVersion, _T("")) == 0) ||
- (_tcscmp(szCSDVersion, _T("Service Pack 1")) == 0) ||
- (_tcscmp(szCSDVersion, _T("Service Pack 2")) == 0));
-
-}
-
-OSVersionInfo rfb::win32::osVersion;
+++ /dev/null
-/* 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.
- */
-
-// -=- OSVersion.h
-
-// Operating system version info.
-// GetVersionInfo is called once at process initialisation, and any
-// extra flags (such as isWinNT) are calculated and saved at that
-// point. It is assumed that the OS Version seldom changes during a
-// program's execution...
-
-#ifndef __RFB_WIN32_OS_VERSION_H__
-#define __RFB_WIN32_OS_VERSION_H__
-
-#include <windows.h>
-
-namespace rfb {
-
- namespace win32 {
-
- extern struct OSVersionInfo : OSVERSIONINFO {
- OSVersionInfo();
-
- // Is the OS one of the NT family (NT 3.51, NT4.0, 2K, XP, etc.)?
- bool isPlatformNT;
- // Is one of the Windows family?
- bool isPlatformWindows;
-
- // Is this OS one of those that blue-screens when grabbing another desktop (NT4 pre SP3)?
- bool cannotSwitchDesktop;
-
- } osVersion;
-
- };
-
-};
-
-#endif // __RFB_WIN32_OS_VERSION_H__
#include <rfb_win32/Registry.h>
#include <rfb_win32/Security.h>
-#include <rfb_win32/DynamicFn.h>
#include <rdr/MemOutStream.h>
#include <rdr/HexOutStream.h>
#include <rdr/HexInStream.h>
void RegKey::setDACL(const PACL acl, bool inherit) {
DWORD result;
- typedef DWORD (WINAPI *_SetSecurityInfo_proto) (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
- DynamicFn<_SetSecurityInfo_proto> _SetSecurityInfo(_T("advapi32.dll"), "SetSecurityInfo");
- if (!_SetSecurityInfo.isValid())
- throw rdr::SystemException("RegKey::setDACL failed", ERROR_CALL_NOT_IMPLEMENTED);
- if ((result = (*_SetSecurityInfo)(key, SE_REGISTRY_KEY,
+ if ((result = SetSecurityInfo(key, SE_REGISTRY_KEY,
DACL_SECURITY_INFORMATION |
(inherit ? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION),
0, 0, acl, 0)) != ERROR_SUCCESS)
#include <rfb_win32/TsSessions.h>
#include <rfb_win32/CleanDesktop.h>
#include <rfb_win32/CurrentUser.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb_win32/MonitorInfo.h>
#include <rfb_win32/SDisplayCorePolling.h>
#include <rfb_win32/SDisplayCoreWMHooks.h>
"Display device name of the monitor to be remoted, or empty to export the whole desktop.", "");
BoolParameter rfb::win32::SDisplay::removeWallpaper("RemoveWallpaper",
"Remove the desktop wallpaper when the server is in use.", false);
-BoolParameter rfb::win32::SDisplay::removePattern("RemovePattern",
- "Remove the desktop background pattern when the server is in use.", false);
BoolParameter rfb::win32::SDisplay::disableEffects("DisableEffects",
"Disable desktop user interface effects when the server is in use.", false);
// SDisplay
//
-typedef BOOL (WINAPI *_LockWorkStation_proto)();
-DynamicFn<_LockWorkStation_proto> _LockWorkStation(_T("user32.dll"), "LockWorkStation");
-
// -=- Constructor/Destructor
SDisplay::SDisplay()
if (!cut.h) {
vlog.info("ignoring DisconnectAction=Lock - no current user");
} else {
- if (_LockWorkStation.isValid())
- (*_LockWorkStation)();
- else
- ExitWindowsEx(EWX_LOGOFF, 0);
+ LockWorkStation();
}
}
}
// Apply desktop optimisations
cleanDesktop = new CleanDesktop;
- if (removePattern)
- cleanDesktop->disablePattern();
if (removeWallpaper)
cleanDesktop->disableWallpaper();
if (disableEffects)
cleanDesktop->disableEffects();
isWallpaperRemoved = removeWallpaper;
- isPatternRemoved = removePattern;
areEffectsDisabled = disableEffects;
}
}
-bool SDisplay::areHooksAvailable() {
- return WMHooks::areAvailable();
-}
-
-
bool SDisplay::isRestartRequired() {
// - We must restart the SDesktop if:
// 1. We are no longer in the input desktop.
// - Check that the desktop optimisation settings haven't changed
// This isn't very efficient, but it shouldn't change very often!
if ((isWallpaperRemoved != removeWallpaper) ||
- (isPatternRemoved != removePattern) ||
(areEffectsDisabled != disableEffects))
return true;
static BoolParameter disableLocalInputs;
static StringParameter disconnectAction;
static BoolParameter removeWallpaper;
- static BoolParameter removePattern;
static BoolParameter disableEffects;
// -=- Use by VNC Config to determine whether hooks are available
// Desktop optimisation
CleanDesktop* cleanDesktop;
bool isWallpaperRemoved;
- bool isPatternRemoved;
bool areEffectsDisabled;
// Cursor
#include <rfb_win32/SInput.h>
#include <rfb_win32/MonitorInfo.h>
#include <rfb_win32/Service.h>
-#include <rfb_win32/OSVersion.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb_win32/keymap.h>
#include <rdr/Exception.h>
#include <rfb/LogWriter.h>
-#if(defined(INPUT_MOUSE) && defined(RFB_HAVE_MONITORINFO) && defined(MOUSEEVENTF_VIRTUALDESK))
-#define RFB_HAVE_SENDINPUT
-#else
-#pragma message(" NOTE: Not building SendInput support.")
-#endif
-
using namespace rfb;
static LogWriter vlog("SInput");
-#ifdef RFB_HAVE_SENDINPUT
-typedef UINT (WINAPI *_SendInput_proto)(UINT, LPINPUT, int);
-static win32::DynamicFn<_SendInput_proto> _SendInput(_T("user32.dll"), "SendInput");
-#endif
-
//
// -=- Pointer implementation for Win32
//
// The event lies outside the primary monitor. Under Win2K, we can just use
// SendInput, which allows us to provide coordinates scaled to the virtual desktop.
// SendInput is available on all multi-monitor-aware platforms.
-#ifdef RFB_HAVE_SENDINPUT
- if (osVersion.isPlatformNT) {
- if (!_SendInput.isValid())
- throw rdr::Exception("SendInput not available");
- INPUT evt;
- evt.type = INPUT_MOUSE;
- Point vPos(pos.x-GetSystemMetrics(SM_XVIRTUALSCREEN),
- pos.y-GetSystemMetrics(SM_YVIRTUALSCREEN));
- evt.mi.dx = (vPos.x * 65535) / (GetSystemMetrics(SM_CXVIRTUALSCREEN)-1);
- evt.mi.dy = (vPos.y * 65535) / (GetSystemMetrics(SM_CYVIRTUALSCREEN)-1);
- evt.mi.dwFlags = flags | MOUSEEVENTF_VIRTUALDESK;
- evt.mi.dwExtraInfo = 0;
- evt.mi.mouseData = data;
- evt.mi.time = 0;
- if ((*_SendInput)(1, &evt, sizeof(evt)) != 1)
- throw rdr::SystemException("SendInput", GetLastError());
- } else {
- // Under Win9x, this is not addressable by either mouse_event or SendInput
- // *** STUPID KLUDGY HACK ***
- POINT cursorPos; GetCursorPos(&cursorPos);
- ULONG oldSpeed, newSpeed = 10;
- ULONG mouseInfo[3];
- if (flags & MOUSEEVENTF_MOVE) {
- flags &= ~MOUSEEVENTF_ABSOLUTE;
- SystemParametersInfo(SPI_GETMOUSE, 0, &mouseInfo, 0);
- SystemParametersInfo(SPI_GETMOUSESPEED, 0, &oldSpeed, 0);
- vlog.debug("SPI_GETMOUSE %lu, %lu, %lu, speed %lu", mouseInfo[0], mouseInfo[1], mouseInfo[2], oldSpeed);
- ULONG idealMouseInfo[] = {10, 0, 0};
- SystemParametersInfo(SPI_SETMOUSESPEED, 0, &newSpeed, 0);
- SystemParametersInfo(SPI_SETMOUSE, 0, &idealMouseInfo, 0);
- }
- ::mouse_event(flags, pos.x-cursorPos.x, pos.y-cursorPos.y, data, 0);
- if (flags & MOUSEEVENTF_MOVE) {
- SystemParametersInfo(SPI_SETMOUSE, 0, &mouseInfo, 0);
- SystemParametersInfo(SPI_SETMOUSESPEED, 0, &oldSpeed, 0);
- }
- }
-#endif
+ INPUT evt;
+ evt.type = INPUT_MOUSE;
+ Point vPos(pos.x-GetSystemMetrics(SM_XVIRTUALSCREEN),
+ pos.y-GetSystemMetrics(SM_YVIRTUALSCREEN));
+ evt.mi.dx = (vPos.x * 65535) / (GetSystemMetrics(SM_CXVIRTUALSCREEN)-1);
+ evt.mi.dy = (vPos.y * 65535) / (GetSystemMetrics(SM_CYVIRTUALSCREEN)-1);
+ evt.mi.dwFlags = flags | MOUSEEVENTF_VIRTUALDESK;
+ evt.mi.dwExtraInfo = 0;
+ evt.mi.mouseData = data;
+ evt.mi.time = 0;
+ if (SendInput(1, &evt, sizeof(evt)) != 1)
+ throw rdr::SystemException("SendInput", GetLastError());
}
}
"Whether to assume the viewer has already interpreted dead key sequences "
"into latin-1 characters", true);
-static bool oneShift;
-
// The keysymToAscii table transforms a couple of awkward keysyms into their
// ASCII equivalents.
struct keysymToAscii_t {
win32::SKeyboard::SKeyboard()
{
- oneShift = rfb::win32::osVersion.isPlatformWindows;
for (unsigned int i = 0; i < sizeof(keymap) / sizeof(keymap_t); i++) {
vkMap[keymap[i].keysym] = keymap[i].vk;
extendedMap[keymap[i].keysym] = keymap[i].extended;
// -=- Security.cxx
#include <rfb_win32/Security.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb/LogWriter.h>
#include <lmcons.h>
PACL rfb::win32::CreateACL(const AccessEntries& ae, PACL existing_acl) {
- typedef DWORD (WINAPI *_SetEntriesInAcl_proto) (ULONG, PEXPLICIT_ACCESS, PACL, PACL*);
-#ifdef UNICODE
- const char* fnName = "SetEntriesInAclW";
-#else
- const char* fnName = "SetEntriesInAclA";
-#endif
- DynamicFn<_SetEntriesInAcl_proto> _SetEntriesInAcl(_T("advapi32.dll"), fnName);
- if (!_SetEntriesInAcl.isValid())
- throw rdr::SystemException("CreateACL failed; no SetEntriesInAcl", ERROR_CALL_NOT_IMPLEMENTED);
PACL new_dacl;
DWORD result;
- if ((result = (*_SetEntriesInAcl)(ae.entry_count, ae.entries, existing_acl, &new_dacl)) != ERROR_SUCCESS)
+ if ((result = SetEntriesInAcl(ae.entry_count, ae.entries, existing_acl, &new_dacl)) != ERROR_SUCCESS)
throw rdr::SystemException("SetEntriesInAcl", result);
return new_dacl;
}
#include <rfb_win32/Service.h>
#include <rfb_win32/MsgWindow.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb_win32/ModuleFileName.h>
#include <rfb_win32/Registry.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb/Threading.h>
#include <logmessages/messages.h>
#include <rdr/Exception.h>
}
-// -=- Message window derived class used under Win9x to implement stopService
-
-#define WM_SMSG_SERVICE_STOP WM_USER
-
-class ServiceMsgWindow : public MsgWindow {
-public:
- ServiceMsgWindow(const TCHAR* name) : MsgWindow(name) {}
- LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
- switch (msg) {
- case WM_SMSG_SERVICE_STOP:
- service->stop();
- return TRUE;
- }
- return MsgWindow::processMessage(msg, wParam, lParam);
- }
-
- static const TCHAR* baseName;
-};
-
-const TCHAR* ServiceMsgWindow::baseName = _T("ServiceWindow:");
-
-
-// -=- Service main procedure, used under WinNT/2K/XP by the SCM
+// -=- Service main procedure
VOID WINAPI serviceProc(DWORD dwArgc, LPTSTR* lpszArgv) {
vlog.debug("entering %s serviceProc", service->getName());
void
Service::start() {
- if (osVersion.isPlatformNT) {
- SERVICE_TABLE_ENTRY entry[2];
- entry[0].lpServiceName = (TCHAR*)name;
- entry[0].lpServiceProc = serviceProc;
- entry[1].lpServiceName = NULL;
- entry[1].lpServiceProc = NULL;
- vlog.debug("entering dispatcher");
- if (!SetProcessShutdownParameters(0x100, 0))
- vlog.error("unable to set shutdown parameters: %lu", GetLastError());
- service = this;
- if (!StartServiceCtrlDispatcher(entry))
- throw SystemException("unable to start service", GetLastError());
- } else {
-
- // - Create the service window, so the service can be stopped
- TCharArray wndName(_tcslen(getName()) + _tcslen(ServiceMsgWindow::baseName) + 1);
- _tcscpy(wndName.buf, ServiceMsgWindow::baseName);
- _tcscat(wndName.buf, getName());
- ServiceMsgWindow service_window(wndName.buf);
-
- // - Locate the RegisterServiceProcess function
- typedef DWORD (WINAPI * _RegisterServiceProcess_proto)(DWORD, DWORD);
- DynamicFn<_RegisterServiceProcess_proto> _RegisterServiceProcess(_T("kernel32.dll"), "RegisterServiceProcess");
- if (!_RegisterServiceProcess.isValid())
- throw Exception("unable to find RegisterServiceProcess");
-
- // - Run the service
- (*_RegisterServiceProcess)(NULL, 1);
- service = this;
- serviceMain(0, 0);
- (*_RegisterServiceProcess)(NULL, 0);
- }
+ SERVICE_TABLE_ENTRY entry[2];
+ entry[0].lpServiceName = (TCHAR*)name;
+ entry[0].lpServiceProc = serviceProc;
+ entry[1].lpServiceName = NULL;
+ entry[1].lpServiceProc = NULL;
+ vlog.debug("entering dispatcher");
+ if (!SetProcessShutdownParameters(0x100, 0))
+ vlog.error("unable to set shutdown parameters: %lu", GetLastError());
+ service = this;
+ if (!StartServiceCtrlDispatcher(entry))
+ throw SystemException("unable to start service", GetLastError());
}
void
void
Service::setStatus(DWORD state) {
- if (!osVersion.isPlatformNT)
- return;
if (status_handle == 0) {
vlog.debug("warning - cannot setStatus");
return;
bool
rfb::win32::desktopChangeRequired() {
- if (!osVersion.isPlatformNT)
- return false;
-
return !inputDesktopSelected();
}
bool
rfb::win32::changeDesktop() {
- if (!osVersion.isPlatformNT)
- return true;
- if (osVersion.cannotSwitchDesktop)
- return false;
-
return selectInputDesktop();
}
// -=- Ctrl-Alt-Del emulation
-class CADThread : public Thread {
-public:
- CADThread() : Thread("CtrlAltDel Emulator"), result(false) {}
- virtual void run() {
- HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());
-
- if (switchToDesktop(OpenDesktop(_T("Winlogon"), 0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
- DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
- DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
- DESKTOP_SWITCHDESKTOP | GENERIC_WRITE))) {
- PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
- switchToDesktop(old_desktop);
- result = true;
- }
- }
- bool result;
-};
-
bool
rfb::win32::emulateCtrlAltDel() {
- if (!osVersion.isPlatformNT)
- return false;
-
- if (osVersion.dwMajorVersion >= 6) {
- rfb::win32::Handle sessionEventCad =
- CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNCCad");
- SetEvent(sessionEventCad);
- return true;
- }
-
- CADThread* cad_thread = new CADThread();
- vlog.debug("emulate Ctrl-Alt-Del");
- if (cad_thread) {
- cad_thread->start();
- cad_thread->join();
- bool result = cad_thread->result;
- delete cad_thread;
- return result;
- }
- return false;
+ rfb::win32::Handle sessionEventCad =
+ CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNCCad");
+ SetEvent(sessionEventCad);
+ return true;
}
bool rfb::win32::initEventLogLogger(const TCHAR* srcname) {
if (logger)
return false;
- if (osVersion.isPlatformNT) {
- logger = new Logger_EventLog(srcname);
- logger->registerLogger();
- return true;
- } else {
- return false;
- }
+ logger = new Logger_EventLog(srcname);
+ logger->registerLogger();
+ return true;
}
// - Initialise the default service parameters
const TCHAR* defaultcmdline;
- if (osVersion.isPlatformNT)
- defaultcmdline = _T("-service");
- else
- defaultcmdline = _T("-noconsole -service");
+ defaultcmdline = _T("-service");
// - Get the full pathname of our executable
ModuleFileName buffer;
// - Register the service
- if (osVersion.isPlatformNT) {
-
- // - Open the SCM
- ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
- if (!scm)
- throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
-
- // - Add the service
- ServiceHandle service = CreateService(scm,
- name, display, SC_MANAGER_ALL_ACCESS,
- SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
- SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
- cmdline.buf, NULL, NULL, NULL, NULL, NULL);
- if (!service)
- throw rdr::SystemException("unable to create service", GetLastError());
-
- // - Set a description
- SERVICE_DESCRIPTION sdesc = {(LPTSTR)desc};
- ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sdesc);
-
- // - Register the event log source
- RegKey hk, hk2;
-
- hk2.createKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"));
- hk.createKey(hk2, name);
-
- for (i=_tcslen(buffer.buf); i>0; i--) {
- if (buffer.buf[i] == _T('\\')) {
- buffer.buf[i+1] = 0;
- break;
- }
+ // - Open the SCM
+ ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+ if (!scm)
+ throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
+
+ // - Add the service
+ ServiceHandle service = CreateService(scm,
+ name, display, SC_MANAGER_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
+ cmdline.buf, NULL, NULL, NULL, NULL, NULL);
+ if (!service)
+ throw rdr::SystemException("unable to create service", GetLastError());
+
+ // - Set a description
+ SERVICE_DESCRIPTION sdesc = {(LPTSTR)desc};
+ ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sdesc);
+
+ // - Register the event log source
+ RegKey hk, hk2;
+
+ hk2.createKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"));
+ hk.createKey(hk2, name);
+
+ for (i=_tcslen(buffer.buf); i>0; i--) {
+ if (buffer.buf[i] == _T('\\')) {
+ buffer.buf[i+1] = 0;
+ break;
}
+ }
- const TCHAR* dllFilename = _T("logmessages.dll");
- TCharArray dllPath(_tcslen(buffer.buf) + _tcslen(dllFilename) + 1);
- _tcscpy(dllPath.buf, buffer.buf);
- _tcscat(dllPath.buf, dllFilename);
-
- hk.setExpandString(_T("EventMessageFile"), dllPath.buf);
- hk.setInt(_T("TypesSupported"), EVENTLOG_ERROR_TYPE | EVENTLOG_INFORMATION_TYPE);
-
- } else {
+ const TCHAR* dllFilename = _T("logmessages.dll");
+ TCharArray dllPath(_tcslen(buffer.buf) + _tcslen(dllFilename) + 1);
+ _tcscpy(dllPath.buf, buffer.buf);
+ _tcscat(dllPath.buf, dllFilename);
- RegKey services;
- services.createKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"));
- services.setString(name, cmdline.buf);
-
- }
+ hk.setExpandString(_T("EventMessageFile"), dllPath.buf);
+ hk.setInt(_T("TypesSupported"), EVENTLOG_ERROR_TYPE | EVENTLOG_INFORMATION_TYPE);
Sleep(500);
}
bool rfb::win32::unregisterService(const TCHAR* name) {
- if (osVersion.isPlatformNT) {
-
- // - Open the SCM
- ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
- if (!scm)
- throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
-
- // - Create the service
- ServiceHandle service = OpenService(scm, name, SC_MANAGER_ALL_ACCESS);
- if (!service)
- throw rdr::SystemException("unable to locate the service", GetLastError());
- if (!DeleteService(service))
- throw rdr::SystemException("unable to remove the service", GetLastError());
-
- // - Register the event log source
- RegKey hk;
- hk.openKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"));
- hk.deleteKey(name);
-
- } else {
-
- RegKey services;
- services.openKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"));
- services.deleteValue(name);
-
- }
+ // - Open the SCM
+ ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+ if (!scm)
+ throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
+
+ // - Create the service
+ ServiceHandle service = OpenService(scm, name, SC_MANAGER_ALL_ACCESS);
+ if (!service)
+ throw rdr::SystemException("unable to locate the service", GetLastError());
+ if (!DeleteService(service))
+ throw rdr::SystemException("unable to remove the service", GetLastError());
+
+ // - Register the event log source
+ RegKey hk;
+ hk.openKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"));
+ hk.deleteKey(name);
Sleep(500);
// -=- Starting and stopping the service
-HWND findServiceWindow(const TCHAR* name) {
- TCharArray wndName(_tcslen(ServiceMsgWindow::baseName)+_tcslen(name)+1);
- _tcscpy(wndName.buf, ServiceMsgWindow::baseName);
- _tcscat(wndName.buf, name);
- vlog.debug("searching for %s window", wndName.buf);
- return FindWindow(0, wndName.buf);
-}
-
bool rfb::win32::startService(const TCHAR* name) {
- if (osVersion.isPlatformNT) {
- // - Open the SCM
- ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- if (!scm)
- throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
-
- // - Locate the service
- ServiceHandle service = OpenService(scm, name, SERVICE_START);
- if (!service)
- throw rdr::SystemException("unable to open the service", GetLastError());
-
- // - Start the service
- if (!StartService(service, 0, NULL))
- throw rdr::SystemException("unable to start the service", GetLastError());
- } else {
- // - Check there is no service window
- if (findServiceWindow(name))
- throw rdr::Exception("the service is already running");
-
- // - Find the RunServices registry key
- RegKey services;
- services.openKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"));
-
- // - Read the command-line from it
- TCharArray cmdLine(services.getString(name));
-
- // - Start the service
- PROCESS_INFORMATION proc_info;
- STARTUPINFO startup_info;
- ZeroMemory(&startup_info, sizeof(startup_info));
- startup_info.cb = sizeof(startup_info);
- if (!CreateProcess(0, cmdLine.buf, 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, 0, &startup_info, &proc_info)) {
- throw SystemException("unable to start service", GetLastError());
- }
- }
+ // - Open the SCM
+ ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ if (!scm)
+ throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
+
+ // - Locate the service
+ ServiceHandle service = OpenService(scm, name, SERVICE_START);
+ if (!service)
+ throw rdr::SystemException("unable to open the service", GetLastError());
+
+ // - Start the service
+ if (!StartService(service, 0, NULL))
+ throw rdr::SystemException("unable to start the service", GetLastError());
Sleep(500);
}
bool rfb::win32::stopService(const TCHAR* name) {
- if (osVersion.isPlatformNT) {
- // - Open the SCM
- ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- if (!scm)
- throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
-
- // - Locate the service
- ServiceHandle service = OpenService(scm, name, SERVICE_STOP);
- if (!service)
- throw rdr::SystemException("unable to open the service", GetLastError());
-
- // - Start the service
- SERVICE_STATUS status;
- if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
- throw rdr::SystemException("unable to stop the service", GetLastError());
-
- } else {
- // - Find the service window
- HWND service_window = findServiceWindow(name);
- if (!service_window)
- throw Exception("unable to locate running service");
-
- // Tell it to quit
- vlog.debug("sending service stop request");
- if (!SendMessage(service_window, WM_SMSG_SERVICE_STOP, 0, 0))
- throw Exception("unable to stop service");
-
- // Check it's quitting...
- DWORD process_id = 0;
- HANDLE process = 0;
- if (!GetWindowThreadProcessId(service_window, &process_id))
- throw SystemException("unable to verify service has quit", GetLastError());
- process = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, process_id);
- if (!process)
- throw SystemException("unable to obtain service handle", GetLastError());
- int retries = 5;
- vlog.debug("checking status");
- while (retries-- && (WaitForSingleObject(process, 1000) != WAIT_OBJECT_0)) {}
- if (!retries) {
- vlog.debug("failed to quit - terminating");
- // May not have quit because of silly Win9x registry watching bug..
- if (!TerminateProcess(process, 1))
- throw SystemException("unable to terminate process!", GetLastError());
- throw Exception("service failed to quit - called TerminateProcess");
- }
- }
+ // - Open the SCM
+ ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ if (!scm)
+ throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
+
+ // - Locate the service
+ ServiceHandle service = OpenService(scm, name, SERVICE_STOP);
+ if (!service)
+ throw rdr::SystemException("unable to open the service", GetLastError());
+
+ // - Start the service
+ SERVICE_STATUS status;
+ if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
+ throw rdr::SystemException("unable to stop the service", GetLastError());
Sleep(500);
}
DWORD rfb::win32::getServiceState(const TCHAR* name) {
- if (osVersion.isPlatformNT) {
- // - Open the SCM
- ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- if (!scm)
- throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
-
- // - Locate the service
- ServiceHandle service = OpenService(scm, name, SERVICE_INTERROGATE);
- if (!service)
- throw rdr::SystemException("unable to open the service", GetLastError());
-
- // - Get the service status
- SERVICE_STATUS status;
- if (!ControlService(service, SERVICE_CONTROL_INTERROGATE, (SERVICE_STATUS*)&status))
- throw rdr::SystemException("unable to query the service", GetLastError());
-
- return status.dwCurrentState;
- } else {
- HWND service_window = findServiceWindow(name);
- return service_window ? SERVICE_RUNNING : SERVICE_STOPPED;
- }
+ // - Open the SCM
+ ServiceHandle scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ if (!scm)
+ throw rdr::SystemException("unable to open Service Control Manager", GetLastError());
+
+ // - Locate the service
+ ServiceHandle service = OpenService(scm, name, SERVICE_INTERROGATE);
+ if (!service)
+ throw rdr::SystemException("unable to open the service", GetLastError());
+
+ // - Get the service status
+ SERVICE_STATUS status;
+ if (!ControlService(service, SERVICE_CONTROL_INTERROGATE, (SERVICE_STATUS*)&status))
+ throw rdr::SystemException("unable to query the service", GetLastError());
+
+ return status.dwCurrentState;
}
char* rfb::win32::serviceStateName(DWORD state) {
// Win32 service-mode code.
// Derive your service from this code and let it handle the annoying Win32
// service API.
-// The underlying implementation takes care of the differences between
-// Windows NT and Windows 95 based systems
#ifndef __RFB_WIN32_SERVICE_H__
#define __RFB_WIN32_SERVICE_H__
// -=- Routines used by desktop back-end code to manage desktops/window stations
- // Returns false under Win9x
bool desktopChangeRequired();
- // Returns true under Win9x
bool changeDesktop();
// -=- Routines used by the SInput Keyboard class to emulate Ctrl-Alt-Del
- // Returns false under Win9x
bool emulateCtrlAltDel();
// -=- Routines to initialise the Event Log target Logger
- // Returns false under Win9x
bool initEventLogLogger(const TCHAR* srcname);
// -=- Routines to register/unregister the service
*/
#include <rfb_win32/TsSessions.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb/LogWriter.h>
#include <rdr/Exception.h>
#include <tchar.h>
-
-#ifdef ERROR_CTX_WINSTATION_BUSY
-#define RFB_HAVE_WINSTATION_CONNECT
-#else
-#pragma message(" NOTE: Not building WinStationConnect support.")
-#endif
+#include <wtsapi32.h>
static rfb::LogWriter vlog("TsSessions");
namespace rfb {
namespace win32 {
- // Windows XP (and later) functions used to handle session Ids
- typedef BOOLEAN (WINAPI *_WinStationConnect_proto) (HANDLE,ULONG,ULONG,PCWSTR,ULONG);
- DynamicFn<_WinStationConnect_proto> _WinStationConnect(_T("winsta.dll"), "WinStationConnectW");
- typedef DWORD (WINAPI *_WTSGetActiveConsoleSessionId_proto) ();
- DynamicFn<_WTSGetActiveConsoleSessionId_proto> _WTSGetActiveConsoleSessionId(_T("kernel32.dll"), "WTSGetActiveConsoleSessionId");
- typedef BOOL (WINAPI *_ProcessIdToSessionId_proto) (DWORD, DWORD*);
- DynamicFn<_ProcessIdToSessionId_proto> _ProcessIdToSessionId(_T("kernel32.dll"), "ProcessIdToSessionId");
- typedef BOOL (WINAPI *_LockWorkStation_proto)();
- DynamicFn<_LockWorkStation_proto> _LockWorkStation(_T("user32.dll"), "LockWorkStation");
-
-
ProcessSessionId::ProcessSessionId(DWORD processId) {
id = 0;
- if (!_ProcessIdToSessionId.isValid())
- return;
if (processId == (DWORD)-1)
processId = GetCurrentProcessId();
- if (!(*_ProcessIdToSessionId)(GetCurrentProcessId(), &id))
+ if (!ProcessIdToSessionId(GetCurrentProcessId(), &id))
throw rdr::SystemException("ProcessIdToSessionId", GetLastError());
}
ProcessSessionId mySessionId;
ConsoleSessionId::ConsoleSessionId() {
- if (_WTSGetActiveConsoleSessionId.isValid())
- id = (*_WTSGetActiveConsoleSessionId)();
- else
- id = 0;
+ id = WTSGetActiveConsoleSessionId();
}
bool inConsoleSession() {
}
void setConsoleSession(DWORD sessionId) {
-#ifdef RFB_HAVE_WINSTATION_CONNECT
- if (!_WinStationConnect.isValid())
- throw rdr::Exception("WinSta APIs missing");
if (sessionId == (DWORD)-1)
sessionId = mySessionId.id;
// Try to reconnect our session to the console
ConsoleSessionId console;
vlog.info("Console session is %lu", console.id);
- if (!(*_WinStationConnect)(0, sessionId, console.id, L"", 0))
+ if (!WTSConnectSession(sessionId, console.id, (PTSTR)_T(""), 0))
throw rdr::SystemException("Unable to connect session to Console", GetLastError());
// Lock the newly connected session, for security
- if (_LockWorkStation.isValid())
- (*_LockWorkStation)();
-#else
- throw rdr::Exception("setConsoleSession not implemented");
-#endif
+ LockWorkStation();
}
};
// -=- WMCursor.cxx
-// *** DOESN'T SEEM TO WORK WITH GetCursorInfo POS CODE BUILT-IN UNDER NT4SP6
-// *** INSTEAD, WE LOOK FOR Win2000/Win98 OR ABOVE
-
#include <rfb_win32/WMCursor.h>
-#include <rfb_win32/OSVersion.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
static LogWriter vlog("WMCursor");
-
-#ifdef CURSOR_SHOWING
-#define RFB_HAVE_GETCURSORINFO
-#else
-#pragma message(" NOTE: Not building GetCursorInfo support.")
-#endif
-
-#ifdef RFB_HAVE_GETCURSORINFO
-typedef BOOL (WINAPI *_GetCursorInfo_proto)(PCURSORINFO pci);
-DynamicFn<_GetCursorInfo_proto> _GetCursorInfo(_T("user32.dll"), "GetCursorInfo");
-#endif
-
-WMCursor::WMCursor() : hooks(0), use_getCursorInfo(false), cursor(0) {
-#ifdef RFB_HAVE_GETCURSORINFO
- // Check the OS version
- bool is_win98 = (osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
- ((osVersion.dwMajorVersion > 4) ||
- ((osVersion.dwMajorVersion == 4) && (osVersion.dwMinorVersion > 0)));
- bool is_win2K = (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVersion.dwMajorVersion >= 5);
-
- // Use GetCursorInfo if OS version is sufficient
- use_getCursorInfo = (is_win98 || is_win2K) && _GetCursorInfo.isValid();
-#endif
+WMCursor::WMCursor() : cursor(0) {
cursor = (HCURSOR)LoadImage(0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
- if (!use_getCursorInfo) {
- hooks = new WMCursorHooks();
- if (hooks && hooks->start()) {
- vlog.info("falling back to cursor hooking: %p", hooks);
- } else {
- delete hooks;
- hooks = 0;
- vlog.error("unable to monitor cursor shape");
- }
- } else {
- vlog.info("using GetCursorInfo");
- }
}
WMCursor::~WMCursor() {
- vlog.debug("deleting WMCursorHooks (%p)", hooks);
- if (hooks)
- delete hooks;
}
WMCursor::Info
WMCursor::getCursorInfo() {
Info result;
-#ifdef RFB_HAVE_GETCURSORINFO
- if (use_getCursorInfo) {
- CURSORINFO info;
- info.cbSize = sizeof(CURSORINFO);
- if ((*_GetCursorInfo)(&info)) {
- result.cursor = info.hCursor;
- result.position = Point(info.ptScreenPos.x, info.ptScreenPos.y);
- result.visible = info.flags & CURSOR_SHOWING;
- return result;
- }
- }
-#endif
- // Fall back to the old way of doing things
- POINT pos;
- if (hooks)
- cursor = hooks->getCursor();
- result.cursor = cursor;
- result.visible = cursor != 0;
- GetCursorPos(&pos);
- result.position.x = pos.x;
- result.position.y = pos.y;
+ CURSORINFO info;
+ info.cbSize = sizeof(CURSORINFO);
+ if (!GetCursorInfo(&info))
+ throw rdr::SystemException("GetCursorInfo failed", GetLastError());
+ result.cursor = info.hCursor;
+ result.position = Point(info.ptScreenPos.x, info.ptScreenPos.y);
+ result.visible = info.flags & CURSOR_SHOWING;
return result;
}
Info getCursorInfo();
protected:
- WMCursorHooks* hooks;
- bool use_getCursorInfo;
HCURSOR cursor;
};
// -=- WMHooks.cxx
#include <rfb_win32/WMHooks.h>
-#include <rfb_win32/DynamicFn.h>
#include <rfb_win32/Service.h>
#include <rfb_win32/MsgWindow.h>
#include <rfb_win32/IntervalTimer.h>
static LogWriter vlog("WMHooks");
+static HMODULE hooksLibrary;
+
typedef UINT (*WM_Hooks_WMVAL_proto)();
+static WM_Hooks_WMVAL_proto WM_Hooks_WindowChanged;
+static WM_Hooks_WMVAL_proto WM_Hooks_WindowBorderChanged;
+static WM_Hooks_WMVAL_proto WM_Hooks_WindowClientAreaChanged;
+static WM_Hooks_WMVAL_proto WM_Hooks_RectangleChanged;
+#ifdef _DEBUG
+static WM_Hooks_WMVAL_proto WM_Hooks_Diagnostic;
+#endif
+
typedef BOOL (*WM_Hooks_Install_proto)(DWORD owner, DWORD thread);
+static WM_Hooks_Install_proto WM_Hooks_Install;
typedef BOOL (*WM_Hooks_Remove_proto)(DWORD owner);
-typedef BOOL (*WM_Hooks_EnableCursorShape_proto)(BOOL enable);
+static WM_Hooks_Remove_proto WM_Hooks_Remove;
#ifdef _DEBUG
typedef void (*WM_Hooks_SetDiagnosticRange_proto)(UINT min, UINT max);
-DynamicFn<WM_Hooks_SetDiagnosticRange_proto> WM_Hooks_SetDiagnosticRange(_T("wm_hooks.dll"), "WM_Hooks_SetDiagnosticRange");
+static WM_Hooks_SetDiagnosticRange_proto WM_Hooks_SetDiagnosticRange;
+#endif
+
+typedef BOOL (*WM_Hooks_EnableRealInputs_proto)(BOOL pointer, BOOL keyboard);
+static WM_Hooks_EnableRealInputs_proto WM_Hooks_EnableRealInputs;
+
+
+static void LoadHooks()
+{
+ if (hooksLibrary != NULL)
+ return;
+
+ hooksLibrary = LoadLibrary("wm_hooks.dll");
+ if (hooksLibrary == NULL)
+ return;
+
+ WM_Hooks_WindowChanged = (WM_Hooks_WMVAL_proto)GetProcAddress(hooksLibrary, "WM_Hooks_WindowChanged");
+ if (WM_Hooks_WindowChanged == NULL)
+ goto error;
+ WM_Hooks_WindowBorderChanged = (WM_Hooks_WMVAL_proto)GetProcAddress(hooksLibrary, "WM_Hooks_WindowBorderChanged");
+ if (WM_Hooks_WindowBorderChanged == NULL)
+ goto error;
+ WM_Hooks_WindowClientAreaChanged = (WM_Hooks_WMVAL_proto)GetProcAddress(hooksLibrary, "WM_Hooks_WindowClientAreaChanged");
+ if (WM_Hooks_WindowClientAreaChanged == NULL)
+ goto error;
+ WM_Hooks_RectangleChanged = (WM_Hooks_WMVAL_proto)GetProcAddress(hooksLibrary, "WM_Hooks_RectangleChanged");
+ if (WM_Hooks_RectangleChanged == NULL)
+ goto error;
+#ifdef _DEBUG
+ WM_Hooks_Diagnostic = (WM_Hooks_WMVAL_proto)GetProcAddress(hooksLibrary, "WM_Hooks_Diagnostic");
+ if (WM_Hooks_Diagnostic == NULL)
+ goto error;
+#endif
+
+ WM_Hooks_Install = (WM_Hooks_Install_proto)GetProcAddress(hooksLibrary, "WM_Hooks_Install");
+ if (WM_Hooks_Install == NULL)
+ goto error;
+ WM_Hooks_Remove = (WM_Hooks_Remove_proto)GetProcAddress(hooksLibrary, "WM_Hooks_Remove");
+ if (WM_Hooks_Remove == NULL)
+ goto error;
+#ifdef _DEBUG
+ WM_Hooks_SetDiagnosticRange = (WM_Hooks_SetDiagnosticRange_proto)GetProcAddress(hooksLibrary, "WM_Hooks_SetDiagnosticRange");
+ if (WM_Hooks_SetDiagnosticRange == NULL)
+ goto error;
#endif
+ WM_Hooks_EnableRealInputs = (WM_Hooks_EnableRealInputs_proto)GetProcAddress(hooksLibrary, "WM_Hooks_EnableRealInputs");
+ if (WM_Hooks_EnableRealInputs == NULL)
+ goto error;
+
+ return;
+
+error:
+ FreeLibrary(hooksLibrary);
+ hooksLibrary = NULL;
+}
+
class WMHooksThread : public Thread {
public:
WMHooksThread() : Thread("WMHookThread"),
- WM_Hooks_Install(_T("wm_hooks.dll"), "WM_Hooks_Install"),
- WM_Hooks_Remove(_T("wm_hooks.dll"), "WM_Hooks_Remove"),
- WM_Hooks_EnableCursorShape(_T("wm_hooks.dll"), "WM_Hooks_EnableCursorShape"),
active(true) {
}
virtual void run();
virtual Thread* join();
- DynamicFn<WM_Hooks_Install_proto> WM_Hooks_Install;;
- DynamicFn<WM_Hooks_Remove_proto> WM_Hooks_Remove;
- DynamicFn<WM_Hooks_EnableCursorShape_proto> WM_Hooks_EnableCursorShape;
protected:
bool active;
};
-WMHooksThread* hook_mgr = 0;
-std::list<WMHooks*> hooks;
-std::list<WMCursorHooks*> cursor_hooks;
-Mutex hook_mgr_lock;
-HCURSOR hook_cursor = (HCURSOR)LoadImage(0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+static WMHooksThread* hook_mgr = 0;
+static std::list<WMHooks*> hooks;
+static Mutex hook_mgr_lock;
static bool StartHookThread() {
if (hook_mgr)
return true;
+ if (hooksLibrary == NULL)
+ return false;
vlog.debug("creating thread");
hook_mgr = new WMHooksThread();
- if (!hook_mgr->WM_Hooks_Install.isValid() ||
- !hook_mgr->WM_Hooks_Remove.isValid()) {
- vlog.debug("hooks not available");
- return false;
- }
vlog.debug("installing hooks");
- if (!(*hook_mgr->WM_Hooks_Install)(hook_mgr->getThreadId(), 0)) {
+ if (!WM_Hooks_Install(hook_mgr->getThreadId(), 0)) {
vlog.error("failed to initialise hooks");
delete hook_mgr->join();
hook_mgr = 0;
static void StopHookThread() {
if (!hook_mgr)
return;
- if (!hooks.empty() || !cursor_hooks.empty())
+ if (!hooks.empty())
return;
vlog.debug("closing thread");
delete hook_mgr->join();
return true;
}
-static bool AddCursorHook(WMCursorHooks* hook) {
- vlog.debug("adding cursor hook");
- Lock l(hook_mgr_lock);
- if (!StartHookThread())
- return false;
- if (!hook_mgr->WM_Hooks_EnableCursorShape.isValid())
- return false;
- if (cursor_hooks.empty() && !(*hook_mgr->WM_Hooks_EnableCursorShape)(TRUE))
- return false;
- cursor_hooks.push_back(hook);
- return true;
-}
-
static bool RemHook(WMHooks* hook) {
{
vlog.debug("removing hook");
return true;
}
-static bool RemCursorHook(WMCursorHooks* hook) {
- {
- vlog.debug("removing cursor hook");
- Lock l(hook_mgr_lock);
- cursor_hooks.remove(hook);
- if (hook_mgr->WM_Hooks_EnableCursorShape.isValid() &&
- cursor_hooks.empty())
- (*hook_mgr->WM_Hooks_EnableCursorShape)(FALSE);
- }
- StopHookThread();
- return true;
-}
-
static void NotifyHooksRegion(const Region& r) {
Lock l(hook_mgr_lock);
std::list<WMHooks*>::iterator i;
(*i)->NotifyHooksRegion(r);
}
-static void NotifyHooksCursor(HCURSOR c) {
- Lock l(hook_mgr_lock);
- hook_cursor = c;
-}
-
-
-static UINT GetMsgVal(DynamicFn<WM_Hooks_WMVAL_proto>& fn) {
- if (fn.isValid())
- return (*fn)();
- return WM_NULL;
-}
void
WMHooksThread::run() {
// Obtain message ids for all supported hook messages
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_WindowChanged(_T("wm_hooks.dll"), "WM_Hooks_WindowChanged");
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_WindowBorderChanged(_T("wm_hooks.dll"), "WM_Hooks_WindowBorderChanged");
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_WindowClientAreaChanged(_T("wm_hooks.dll"), "WM_Hooks_WindowClientAreaChanged");
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_RectangleChanged(_T("wm_hooks.dll"), "WM_Hooks_RectangleChanged");
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_CursorChanged(_T("wm_hooks.dll"), "WM_Hooks_CursorChanged");
- UINT windowMsg = GetMsgVal(WM_Hooks_WindowChanged);
- UINT clientAreaMsg = GetMsgVal(WM_Hooks_WindowClientAreaChanged);
- UINT borderMsg = GetMsgVal(WM_Hooks_WindowBorderChanged);
- UINT rectangleMsg = GetMsgVal(WM_Hooks_RectangleChanged);
- UINT cursorMsg = GetMsgVal(WM_Hooks_CursorChanged);
+ UINT windowMsg = WM_Hooks_WindowChanged();
+ UINT clientAreaMsg = WM_Hooks_WindowClientAreaChanged();
+ UINT borderMsg = WM_Hooks_WindowBorderChanged();
+ UINT rectangleMsg = WM_Hooks_RectangleChanged();
#ifdef _DEBUG
- DynamicFn<WM_Hooks_WMVAL_proto> WM_Hooks_Diagnostic(_T("wm_hooks.dll"), "WM_Hooks_Diagnostic");
- UINT diagnosticMsg = GetMsgVal(WM_Hooks_Diagnostic);
+ UINT diagnosticMsg = WM_Hooks_Diagnostic();
#endif
MSG msg;
RECT wrect;
updateDelayTimer.start(updateDelayMs);
}
- } else if (msg.message == cursorMsg) {
- NotifyHooksCursor((HCURSOR)msg.lParam);
#ifdef _DEBUG
} else if (msg.message == diagnosticMsg) {
vlog.info("DIAG msg=%x(%d) wnd=%lx",
}
vlog.debug("stopping hook thread - processed %d events", count);
- (*WM_Hooks_Remove)(getThreadId());
+ WM_Hooks_Remove(getThreadId());
}
Thread*
// -=- WMHooks class
rfb::win32::WMHooks::WMHooks() : updateEvent(0) {
+ LoadHooks();
}
rfb::win32::WMHooks::~WMHooks() {
return true;
}
-bool rfb::win32::WMHooks::areAvailable() {
- WMHooksThread wmht;
- return wmht.WM_Hooks_Install.isValid();
-}
-
#ifdef _DEBUG
void
rfb::win32::WMHooks::setDiagnosticRange(UINT min, UINT max) {
- if (WM_Hooks_SetDiagnosticRange.isValid())
- (*WM_Hooks_SetDiagnosticRange)(min, max);
+ WM_Hooks_SetDiagnosticRange(min, max);
}
#endif
// -=- WMBlockInput class
rfb::win32::WMBlockInput::WMBlockInput() : active(false) {
+ LoadHooks();
}
rfb::win32::WMBlockInput::~WMBlockInput() {
blockInputs(false);
}
-typedef BOOL (*WM_Hooks_EnableRealInputs_proto)(BOOL pointer, BOOL keyboard);
-DynamicFn<WM_Hooks_EnableRealInputs_proto>* WM_Hooks_EnableRealInputs = 0;
+static bool blocking = false;
static bool blockRealInputs(bool block_) {
// NB: Requires blockMutex to be held!
+ if (hooksLibrary == NULL)
+ return false;
if (block_) {
- if (WM_Hooks_EnableRealInputs)
+ if (blocking)
return true;
// Enable blocking
- WM_Hooks_EnableRealInputs = new DynamicFn<WM_Hooks_EnableRealInputs_proto>(_T("wm_hooks.dll"), "WM_Hooks_EnableRealInputs");
- if (WM_Hooks_EnableRealInputs->isValid() && (**WM_Hooks_EnableRealInputs)(false, false))
- return true;
+ if (!WM_Hooks_EnableRealInputs(false, false))
+ return false;
+ blocking = true;
}
- if (WM_Hooks_EnableRealInputs) {
- // Clean up the DynamicFn, either if init failed, or block_ is false
- if (WM_Hooks_EnableRealInputs->isValid())
- (**WM_Hooks_EnableRealInputs)(true, true);
- delete WM_Hooks_EnableRealInputs;
- WM_Hooks_EnableRealInputs = 0;
+ if (blocking) {
+ WM_Hooks_EnableRealInputs(true, true);
+ blocking = false;
}
- return block_ == (WM_Hooks_EnableRealInputs != 0);
+ return block_ == blocking;
}
Mutex blockMutex;
active = on;
return true;
}
-
-
-// -=- WMCursorHooks class
-
-rfb::win32::WMCursorHooks::WMCursorHooks() {
-}
-
-rfb::win32::WMCursorHooks::~WMCursorHooks() {
- RemCursorHook(this);
-}
-
-bool
-rfb::win32::WMCursorHooks::start() {
- return AddCursorHook(this);
-}
-
-HCURSOR
-rfb::win32::WMCursorHooks::getCursor() const {
- return hook_cursor;
-}
// were added, false otherwise.
bool getUpdates(UpdateTracker* ut);
- // Determine whether the hooks DLL is installed on the system
- static bool areAvailable();
-
#ifdef _DEBUG
// Get notifications of any messages in the given range, to any hooked window
void setDiagnosticRange(UINT min, UINT max);
bool active;
};
- // - Legacy cursor handling support
- class WMCursorHooks {
- public:
- WMCursorHooks();
- ~WMCursorHooks();
-
- bool start();
-
- HCURSOR getCursor() const;
- };
-
};
};
#include <vncconfig/PasswordDialog.h>
#include <rfb_win32/Registry.h>
#include <rfb_win32/SecurityPage.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb_win32/MsgBox.h>
#include <rfb/ServerCore.h>
#include <rfb/Security.h>
registryInsecure = warn;
}
bool enableQueryOnlyIfLoggedOn() {
- return isItemChecked(IDC_QUERY_CONNECT) && osVersion.isPlatformNT && (osVersion.dwMajorVersion >= 5);
+ return isItemChecked(IDC_QUERY_CONNECT);
}
#include <rfb_win32/Registry.h>
#include <rfb_win32/Dialog.h>
#include <rfb_win32/SDisplay.h>
-#include <rfb_win32/DynamicFn.h>
namespace rfb {
CharArray action(rfb::win32::SDisplay::disconnectAction.getData());
bool disconnectLock = stricmp(action.buf, "Lock") == 0;
bool disconnectLogoff = stricmp(action.buf, "Logoff") == 0;
- typedef BOOL (WINAPI *_LockWorkStation_proto)();
- DynamicFn<_LockWorkStation_proto> _LockWorkStation(_T("user32.dll"), "LockWorkStation");
- if (!_LockWorkStation.isValid()) {
- enableItem(IDC_DISCONNECT_LOCK, false);
- if (disconnectLock) {
- disconnectLogoff = true;
- disconnectLock = false;
- }
- }
setItemChecked(IDC_DISCONNECT_LOGOFF, disconnectLogoff);
setItemChecked(IDC_DISCONNECT_LOCK, disconnectLock);
setItemChecked(IDC_DISCONNECT_NONE, !disconnectLock && !disconnectLogoff);
setItemChecked(IDC_REMOVE_WALLPAPER, rfb::win32::SDisplay::removeWallpaper);
- setItemChecked(IDC_REMOVE_PATTERN, rfb::win32::SDisplay::removePattern);
setItemChecked(IDC_DISABLE_EFFECTS, rfb::win32::SDisplay::disableEffects);
}
bool onCommand(int id, int cmd) {
case IDC_DISCONNECT_LOCK:
case IDC_DISCONNECT_NONE:
case IDC_REMOVE_WALLPAPER:
- case IDC_REMOVE_PATTERN:
case IDC_DISABLE_EFFECTS:
CharArray action(rfb::win32::SDisplay::disconnectAction.getData());
bool disconnectLock = stricmp(action.buf, "Lock") == 0;
setChanged((disconnectLogoff != isItemChecked(IDC_DISCONNECT_LOGOFF)) ||
(disconnectLock != isItemChecked(IDC_DISCONNECT_LOCK)) ||
(isItemChecked(IDC_REMOVE_WALLPAPER) != rfb::win32::SDisplay::removeWallpaper) ||
- (isItemChecked(IDC_REMOVE_PATTERN) != rfb::win32::SDisplay::removePattern) ||
(isItemChecked(IDC_DISABLE_EFFECTS) != rfb::win32::SDisplay::disableEffects));
break;
}
action = _T("Lock");
regKey.setString(_T("DisconnectAction"), action);
regKey.setBool(_T("RemoveWallpaper"), isItemChecked(IDC_REMOVE_WALLPAPER));
- regKey.setBool(_T("RemovePattern"), isItemChecked(IDC_REMOVE_PATTERN));
regKey.setBool(_T("DisableEffects"), isItemChecked(IDC_DISABLE_EFFECTS));
return true;
}
: PropSheetPage(GetModuleHandle(0), MAKEINTRESOURCE(IDD_HOOKING)), regKey(rk) {}
void initDialog() {
setItemChecked(IDC_USEPOLLING, rfb::win32::SDisplay::updateMethod == 0);
- setItemChecked(IDC_USEHOOKS, (rfb::win32::SDisplay::updateMethod == 1) &&
- rfb::win32::SDisplay::areHooksAvailable());
- enableItem(IDC_USEHOOKS, rfb::win32::SDisplay::areHooksAvailable());
+ setItemChecked(IDC_USEHOOKS, (rfb::win32::SDisplay::updateMethod == 1));
setItemChecked(IDC_POLLCONSOLES, rfb::win32::WMPoller::poll_console_windows);
- setItemChecked(IDC_CAPTUREBLT, osVersion.isPlatformNT &&
- rfb::win32::DeviceFrameBuffer::useCaptureBlt);
- enableItem(IDC_CAPTUREBLT, osVersion.isPlatformNT);
+ setItemChecked(IDC_CAPTUREBLT, rfb::win32::DeviceFrameBuffer::useCaptureBlt);
onCommand(IDC_USEHOOKS, 0);
}
bool onCommand(int id, int cmd) {
#include <rfb_win32/Registry.h>
#include <rfb_win32/Dialog.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb/ServerCore.h>
namespace rfb {
setItemChecked(IDC_ACCEPT_CUTTEXT, rfb::Server::acceptCutText);
setItemChecked(IDC_SEND_CUTTEXT, rfb::Server::sendCutText);
setItemChecked(IDC_DISABLE_LOCAL_INPUTS, SDisplay::disableLocalInputs);
- enableItem(IDC_DISABLE_LOCAL_INPUTS, !osVersion.isPlatformWindows);
BOOL blocked = FALSE;
if (SystemParametersInfo(SPI_GETBLOCKSENDINPUTRESETS, 0, &blocked, 0))
setItemChecked(IDC_AFFECT_SCREENSAVER, !blocked);
regKey.setInt(_T("IdleTimeout"), key.getInt(_T("IdleTimeout"), 0));
regKey.setBool(_T("RemoveWallpaper"), key.getBool(_T("RemoveWallpaper")));
- regKey.setBool(_T("RemovePattern"), key.getBool(_T("RemoveWallpaper")));
- regKey.setBool(_T("DisableEffects"), key.getBool(_T("RemoveWallpaper")));
+ regKey.setBool(_T("DisableEffects"), key.getBool(_T("DisableEffects")));
if (key.getInt(_T("QuerySetting"), 2) != 2) {
regKey.setBool(_T("QueryConnect"), key.getInt(_T("QuerySetting")) > 2);
#define IDC_DISCONNECT_LOCK 1057
#define IDC_DISCONNECT_LOGOFF 1058
#define IDC_REMOVE_WALLPAPER 1059
-#define IDC_REMOVE_PATTERN 1060
#define IDC_DISABLE_EFFECTS 1061
#define IDC_CAPTUREBLT 1062
#define IDC_QUERY 1064
} else if (e.err != ERROR_CALL_NOT_IMPLEMENTED &&
e.err != ERROR_NOT_LOGGED_ON) {
// If the call is not implemented, ignore the error and continue
- // If we are on Win9x and no user is logged on, ignore error and continue
throw;
}
warnOnChangePassword = true;
CAPTION "Desktop"
FONT 8, "MS Sans Serif"
BEGIN
- GROUPBOX "While connected",IDC_STATIC,7,5,171,60
+ GROUPBOX "While connected",IDC_STATIC,7,5,171,45
CONTROL "Remove wallpaper",IDC_REMOVE_WALLPAPER,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,15,15,155,15
- CONTROL "Remove background pattern",IDC_REMOVE_PATTERN,"Button",
- BS_AUTOCHECKBOX | WS_TABSTOP,15,30,155,15
CONTROL "Disable user interface effects",IDC_DISABLE_EFFECTS,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,46,155,14
- GROUPBOX "When last client disconnects",IDC_STATIC,7,70,171,60
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,30,155,14
+ GROUPBOX "When last client disconnects",IDC_STATIC,7,55,171,60
CONTROL "Do nothing",IDC_DISCONNECT_NONE,"Button",
- BS_AUTORADIOBUTTON,15,80,155,15
+ BS_AUTORADIOBUTTON,15,65,155,15
CONTROL "Lock workstation",IDC_DISCONNECT_LOCK,"Button",
- BS_AUTORADIOBUTTON,15,95,155,15
+ BS_AUTORADIOBUTTON,15,80,155,15
CONTROL "Logoff user",IDC_DISCONNECT_LOGOFF,"Button",
- BS_AUTORADIOBUTTON,15,110,155,15
+ BS_AUTORADIOBUTTON,15,95,155,15
END
// -=- WinVNC Version 4.0 Service-Mode implementation
#include <winvnc/VNCServerService.h>
-#include <rfb_win32/OSVersion.h>
#include <rfb_win32/TsSessions.h>
#include <rfb_win32/ModuleFileName.h>
+#include <windows.h>
#include <wtsapi32.h>
#include <tlhelp32.h>
const TCHAR* winvnc::VNCServerService::Name = _T("TigerVNC");
+// SendSAS is not available until Windows 7, and missing from MinGW
+static HMODULE sasLibrary = NULL;
+typedef void WINAPI (*SendSAS_proto)(BOOL AsUser);
+static SendSAS_proto _SendSAS = NULL;
+
VNCServerService::VNCServerService()
: Service(Name)
- , SendSas(_T("sas.dll"), "SendSAS")
, stopServiceEvent(CreateEvent(0, FALSE, FALSE, 0))
, sessionEvent(CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNC"))
, sessionEventCad(CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNCCad")) {
+ if (sasLibrary == NULL) {
+ sasLibrary = LoadLibrary("sas.dll");
+ if (sasLibrary != NULL)
+ _SendSAS = (SendSAS_proto)GetProcAddress(sasLibrary, "SendSAS");
+ }
// - Set the service-mode logging defaults
// These will be overridden by the Log option in the
// registry, if present.
- if (osVersion.isPlatformNT)
- logParams.setParam("*:EventLog:0,Connections:EventLog:100");
- else
- logParams.setParam("*:file:0,Connections:file:100");
+ logParams.setParam("*:EventLog:0,Connections:EventLog:100");
}
//cad request
case WAIT_OBJECT_0 + 1:
- if (SendSas.isValid())
- (*SendSas)(FALSE);
+ if (_SendSAS != NULL)
+ _SendSAS(FALSE);
break;
case WAIT_TIMEOUT:
#include <winvnc/VNCServerWin32.h>
#include <rfb_win32/Service.h>
-#include <rfb_win32/DynamicFn.h>
namespace winvnc {
static const TCHAR* Name;
protected:
- rfb::win32::DynamicFn<void (WINAPI *)(BOOL)> SendSas;
rfb::win32::Handle stopServiceEvent;
rfb::win32::Handle sessionEvent;
rfb::win32::Handle sessionEventCad;