diff options
33 files changed, 288 insertions, 1086 deletions
diff --git a/win/rfb_win32/CMakeLists.txt b/win/rfb_win32/CMakeLists.txt index 99d52779..047b0d86 100644 --- a/win/rfb_win32/CMakeLists.txt +++ b/win/rfb_win32/CMakeLists.txt @@ -6,13 +6,11 @@ set(RFB_WIN32_SOURCES 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 @@ -40,4 +38,4 @@ endif() 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) diff --git a/win/rfb_win32/CleanDesktop.cxx b/win/rfb_win32/CleanDesktop.cxx index 8009fc8b..69fa6667 100644 --- a/win/rfb_win32/CleanDesktop.cxx +++ b/win/rfb_win32/CleanDesktop.cxx @@ -24,18 +24,11 @@ #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; @@ -154,14 +147,14 @@ DWORD SysParamsInfo(UINT action, UINT param, PVOID ptr, UINT ini) { } -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(); } @@ -221,42 +214,6 @@ void CleanDesktop::enableWallpaper() { } -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; @@ -264,7 +221,6 @@ void CleanDesktop::disableEffects() { 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); @@ -282,9 +238,6 @@ void CleanDesktop::disableEffects() { // 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) { @@ -302,7 +255,6 @@ void CleanDesktop::enableEffects() { 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); @@ -311,9 +263,6 @@ void CleanDesktop::enableEffects() { SysParamsInfo(SPI_SETMENUANIMATION, 0, (void*)(intptr_t)menuAnim, SPIF_SENDCHANGE); } restoreEffects = false; -#else - vlog.info(" not supported"); -#endif } } catch (rdr::Exception& e) { diff --git a/win/rfb_win32/CurrentUser.cxx b/win/rfb_win32/CurrentUser.cxx index 21531de8..6be3f9ab 100644 --- a/win/rfb_win32/CurrentUser.cxx +++ b/win/rfb_win32/CurrentUser.cxx @@ -21,10 +21,9 @@ #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; @@ -68,48 +67,18 @@ BOOL CALLBACK enumDesktops(LPTSTR lpszDesktop, LPARAM lParam) { } -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; } } diff --git a/win/rfb_win32/CurrentUser.h b/win/rfb_win32/CurrentUser.h index 794f27c6..9c020887 100644 --- a/win/rfb_win32/CurrentUser.h +++ b/win/rfb_win32/CurrentUser.h @@ -38,17 +38,6 @@ namespace rfb { // 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. // @@ -56,18 +45,15 @@ namespace rfb { 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 { @@ -79,8 +65,6 @@ namespace rfb { // 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(); diff --git a/win/rfb_win32/DeviceFrameBuffer.cxx b/win/rfb_win32/DeviceFrameBuffer.cxx index d075c259..22841f7e 100644 --- a/win/rfb_win32/DeviceFrameBuffer.cxx +++ b/win/rfb_win32/DeviceFrameBuffer.cxx @@ -25,7 +25,6 @@ #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> @@ -108,10 +107,9 @@ DeviceFrameBuffer::grabRect(const Rect &rect) { // 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 diff --git a/win/rfb_win32/DynamicFn.cxx b/win/rfb_win32/DynamicFn.cxx deleted file mode 100644 index 97d17ff7..00000000 --- a/win/rfb_win32/DynamicFn.cxx +++ /dev/null @@ -1,45 +0,0 @@ -/* 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); -} - - diff --git a/win/rfb_win32/DynamicFn.h b/win/rfb_win32/DynamicFn.h deleted file mode 100644 index 57fdbec5..00000000 --- a/win/rfb_win32/DynamicFn.h +++ /dev/null @@ -1,51 +0,0 @@ -/* 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 diff --git a/win/rfb_win32/MonitorInfo.cxx b/win/rfb_win32/MonitorInfo.cxx index d639ac56..551017bd 100644 --- a/win/rfb_win32/MonitorInfo.cxx +++ b/win/rfb_win32/MonitorInfo.cxx @@ -16,7 +16,7 @@ * USA. */ -#include <rfb_win32/DynamicFn.h> +#include <tchar.h> #include <rfb_win32/MonitorInfo.h> #include <rfb_win32/Win32Util.h> #include <rdr/Exception.h> @@ -36,91 +36,39 @@ using namespace win32; 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; @@ -133,7 +81,7 @@ static BOOL CALLBACK monitorByNameEnumProc(HMONITOR monitor, 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; } @@ -141,44 +89,21 @@ static BOOL CALLBACK monitorByNameEnumProc(HMONITOR monitor, 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) { diff --git a/win/rfb_win32/MonitorInfo.h b/win/rfb_win32/MonitorInfo.h index acf27755..2179b9b2 100644 --- a/win/rfb_win32/MonitorInfo.h +++ b/win/rfb_win32/MonitorInfo.h @@ -17,35 +17,18 @@ */ // 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); diff --git a/win/rfb_win32/OSVersion.cxx b/win/rfb_win32/OSVersion.cxx deleted file mode 100644 index 3d74c956..00000000 --- a/win/rfb_win32/OSVersion.cxx +++ /dev/null @@ -1,47 +0,0 @@ -/* 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; diff --git a/win/rfb_win32/OSVersion.h b/win/rfb_win32/OSVersion.h deleted file mode 100644 index 18ec003e..00000000 --- a/win/rfb_win32/OSVersion.h +++ /dev/null @@ -1,53 +0,0 @@ -/* 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__ diff --git a/win/rfb_win32/Registry.cxx b/win/rfb_win32/Registry.cxx index 70083f4a..afbdd067 100644 --- a/win/rfb_win32/Registry.cxx +++ b/win/rfb_win32/Registry.cxx @@ -20,7 +20,6 @@ #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> @@ -100,11 +99,7 @@ void RegKey::openKey(const RegKey& root, const TCHAR* name, bool readOnly) { 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) diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx index d4cedf8c..ac64e3ef 100644 --- a/win/rfb_win32/SDisplay.cxx +++ b/win/rfb_win32/SDisplay.cxx @@ -25,7 +25,6 @@ #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> @@ -51,8 +50,6 @@ StringParameter displayDevice("DisplayDevice", "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); @@ -62,9 +59,6 @@ BoolParameter rfb::win32::SDisplay::disableEffects("DisableEffects", // SDisplay // -typedef BOOL (WINAPI *_LockWorkStation_proto)(); -DynamicFn<_LockWorkStation_proto> _LockWorkStation(_T("user32.dll"), "LockWorkStation"); - // -=- Constructor/Destructor SDisplay::SDisplay() @@ -127,10 +121,7 @@ void SDisplay::stop() if (!cut.h) { vlog.info("ignoring DisconnectAction=Lock - no current user"); } else { - if (_LockWorkStation.isValid()) - (*_LockWorkStation)(); - else - ExitWindowsEx(EWX_LOGOFF, 0); + LockWorkStation(); } } } @@ -199,14 +190,11 @@ void SDisplay::startCore() { // Apply desktop optimisations cleanDesktop = new CleanDesktop; - if (removePattern) - cleanDesktop->disablePattern(); if (removeWallpaper) cleanDesktop->disableWallpaper(); if (disableEffects) cleanDesktop->disableEffects(); isWallpaperRemoved = removeWallpaper; - isPatternRemoved = removePattern; areEffectsDisabled = disableEffects; } @@ -227,11 +215,6 @@ void SDisplay::stopCore() { } -bool SDisplay::areHooksAvailable() { - return WMHooks::areAvailable(); -} - - bool SDisplay::isRestartRequired() { // - We must restart the SDesktop if: // 1. We are no longer in the input desktop. @@ -255,7 +238,6 @@ bool SDisplay::isRestartRequired() { // - 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; diff --git a/win/rfb_win32/SDisplay.h b/win/rfb_win32/SDisplay.h index 70208a7d..b0217822 100644 --- a/win/rfb_win32/SDisplay.h +++ b/win/rfb_win32/SDisplay.h @@ -93,7 +93,6 @@ namespace rfb { 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 @@ -139,7 +138,6 @@ namespace rfb { // Desktop optimisation CleanDesktop* cleanDesktop; bool isWallpaperRemoved; - bool isPatternRemoved; bool areEffectsDisabled; // Cursor diff --git a/win/rfb_win32/SInput.cxx b/win/rfb_win32/SInput.cxx index 111a4d90..0923118a 100644 --- a/win/rfb_win32/SInput.cxx +++ b/win/rfb_win32/SInput.cxx @@ -30,27 +30,14 @@ #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 // @@ -125,44 +112,18 @@ win32::SPointer::pointerEvent(const Point& pos, int buttonmask) // 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()); } } @@ -174,8 +135,6 @@ BoolParameter rfb::win32::SKeyboard::deadKeyAware("DeadKeyAware", "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 { @@ -332,7 +291,6 @@ void doKeyEventWithModifiers(BYTE vkCode, BYTE modifierState, bool down) 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; diff --git a/win/rfb_win32/Security.cxx b/win/rfb_win32/Security.cxx index cad13256..5df20cd7 100644 --- a/win/rfb_win32/Security.cxx +++ b/win/rfb_win32/Security.cxx @@ -19,7 +19,6 @@ // -=- Security.cxx #include <rfb_win32/Security.h> -#include <rfb_win32/DynamicFn.h> #include <rfb/LogWriter.h> #include <lmcons.h> @@ -155,18 +154,9 @@ Sid::FromToken::FromToken(HANDLE 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; } diff --git a/win/rfb_win32/Service.cxx b/win/rfb_win32/Service.cxx index c385fa05..d054ce4d 100644 --- a/win/rfb_win32/Service.cxx +++ b/win/rfb_win32/Service.cxx @@ -20,10 +20,8 @@ #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> @@ -66,29 +64,7 @@ VOID WINAPI serviceHandler(DWORD control) { } -// -=- 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()); @@ -124,38 +100,17 @@ Service::Service(const TCHAR* name_) : name(name_) { 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 @@ -165,8 +120,6 @@ Service::setStatus() { void Service::setStatus(DWORD state) { - if (!osVersion.isPlatformNT) - return; if (status_handle == 0) { vlog.debug("warning - cannot setStatus"); return; @@ -282,65 +235,23 @@ selectInputDesktop() { 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; } @@ -379,13 +290,9 @@ static Logger_EventLog* logger = 0; 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; } @@ -398,10 +305,7 @@ bool rfb::win32::registerService(const TCHAR* name, // - 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; @@ -424,54 +328,44 @@ bool rfb::win32::registerService(const TCHAR* name, // - 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); @@ -479,32 +373,22 @@ bool rfb::win32::registerService(const TCHAR* name, } 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); @@ -514,51 +398,21 @@ bool rfb::win32::unregisterService(const TCHAR* name) { // -=- 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); @@ -566,52 +420,20 @@ bool rfb::win32::startService(const TCHAR* name) { } 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); @@ -619,27 +441,22 @@ bool rfb::win32::stopService(const TCHAR* name) { } 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) { diff --git a/win/rfb_win32/Service.h b/win/rfb_win32/Service.h index cbb6263d..691ad95d 100644 --- a/win/rfb_win32/Service.h +++ b/win/rfb_win32/Service.h @@ -21,8 +21,6 @@ // 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__ @@ -86,18 +84,14 @@ namespace rfb { // -=- 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 diff --git a/win/rfb_win32/TsSessions.cxx b/win/rfb_win32/TsSessions.cxx index b02f6195..6d16adbf 100644 --- a/win/rfb_win32/TsSessions.cxx +++ b/win/rfb_win32/TsSessions.cxx @@ -17,50 +17,28 @@ */ #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() { @@ -69,24 +47,17 @@ namespace win32 { } 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(); } }; diff --git a/win/rfb_win32/WMCursor.cxx b/win/rfb_win32/WMCursor.cxx index fa158335..0ad96f3a 100644 --- a/win/rfb_win32/WMCursor.cxx +++ b/win/rfb_win32/WMCursor.cxx @@ -18,12 +18,7 @@ // -=- 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> @@ -33,73 +28,22 @@ using namespace rfb::win32; 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; } diff --git a/win/rfb_win32/WMCursor.h b/win/rfb_win32/WMCursor.h index 41f9ee84..252cb056 100644 --- a/win/rfb_win32/WMCursor.h +++ b/win/rfb_win32/WMCursor.h @@ -50,8 +50,6 @@ namespace rfb { Info getCursorInfo(); protected: - WMCursorHooks* hooks; - bool use_getCursorInfo; HCURSOR cursor; }; diff --git a/win/rfb_win32/WMHooks.cxx b/win/rfb_win32/WMHooks.cxx index 2a3da0d9..0e5e70a4 100644 --- a/win/rfb_win32/WMHooks.cxx +++ b/win/rfb_win32/WMHooks.cxx @@ -19,7 +19,6 @@ // -=- 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> @@ -34,52 +33,106 @@ using namespace rfb::win32; 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; @@ -93,7 +146,7 @@ static bool StartHookThread() { 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(); @@ -110,19 +163,6 @@ static bool AddHook(WMHooks* hook) { 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"); @@ -133,19 +173,6 @@ static bool RemHook(WMHooks* 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; @@ -153,34 +180,16 @@ static void NotifyHooksRegion(const Region& r) { (*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; @@ -261,8 +270,6 @@ WMHooksThread::run() { 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", @@ -273,7 +280,7 @@ WMHooksThread::run() { } vlog.debug("stopping hook thread - processed %d events", count); - (*WM_Hooks_Remove)(getThreadId()); + WM_Hooks_Remove(getThreadId()); } Thread* @@ -288,6 +295,7 @@ WMHooksThread::join() { // -=- WMHooks class rfb::win32::WMHooks::WMHooks() : updateEvent(0) { + LoadHooks(); } rfb::win32::WMHooks::~WMHooks() { @@ -310,16 +318,10 @@ bool rfb::win32::WMHooks::getUpdates(UpdateTracker* ut) { 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 @@ -334,32 +336,31 @@ void rfb::win32::WMHooks::NotifyHooksRegion(const Region& r) { // -=- 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; @@ -375,23 +376,3 @@ bool rfb::win32::WMBlockInput::blockInputs(bool on) { 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; -} diff --git a/win/rfb_win32/WMHooks.h b/win/rfb_win32/WMHooks.h index 4713b416..c1dbd5f3 100644 --- a/win/rfb_win32/WMHooks.h +++ b/win/rfb_win32/WMHooks.h @@ -47,9 +47,6 @@ namespace rfb { // 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); @@ -74,17 +71,6 @@ namespace rfb { bool active; }; - // - Legacy cursor handling support - class WMCursorHooks { - public: - WMCursorHooks(); - ~WMCursorHooks(); - - bool start(); - - HCURSOR getCursor() const; - }; - }; }; diff --git a/win/vncconfig/Authentication.h b/win/vncconfig/Authentication.h index c2aba91e..7fa85a2f 100644 --- a/win/vncconfig/Authentication.h +++ b/win/vncconfig/Authentication.h @@ -21,7 +21,6 @@ #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> @@ -87,7 +86,7 @@ namespace rfb { registryInsecure = warn; } bool enableQueryOnlyIfLoggedOn() { - return isItemChecked(IDC_QUERY_CONNECT) && osVersion.isPlatformNT && (osVersion.dwMajorVersion >= 5); + return isItemChecked(IDC_QUERY_CONNECT); } diff --git a/win/vncconfig/Desktop.h b/win/vncconfig/Desktop.h index 6479cb26..1a687d74 100644 --- a/win/vncconfig/Desktop.h +++ b/win/vncconfig/Desktop.h @@ -21,7 +21,6 @@ #include <rfb_win32/Registry.h> #include <rfb_win32/Dialog.h> #include <rfb_win32/SDisplay.h> -#include <rfb_win32/DynamicFn.h> namespace rfb { @@ -35,20 +34,10 @@ 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) { @@ -57,7 +46,6 @@ namespace rfb { 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; @@ -65,7 +53,6 @@ namespace rfb { 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; } @@ -79,7 +66,6 @@ namespace rfb { 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; } diff --git a/win/vncconfig/Hooking.h b/win/vncconfig/Hooking.h index b8137ddc..f5ef8b74 100644 --- a/win/vncconfig/Hooking.h +++ b/win/vncconfig/Hooking.h @@ -34,13 +34,9 @@ namespace rfb { : 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) { diff --git a/win/vncconfig/Inputs.h b/win/vncconfig/Inputs.h index 1e0b4bac..2ad3b425 100644 --- a/win/vncconfig/Inputs.h +++ b/win/vncconfig/Inputs.h @@ -25,7 +25,6 @@ #include <rfb_win32/Registry.h> #include <rfb_win32/Dialog.h> -#include <rfb_win32/OSVersion.h> #include <rfb/ServerCore.h> namespace rfb { @@ -42,7 +41,6 @@ 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); diff --git a/win/vncconfig/Legacy.cxx b/win/vncconfig/Legacy.cxx index f8c20280..7d51de81 100644 --- a/win/vncconfig/Legacy.cxx +++ b/win/vncconfig/Legacy.cxx @@ -206,8 +206,7 @@ void LegacyPage::LoadPrefs() 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); diff --git a/win/vncconfig/resource.h b/win/vncconfig/resource.h index 7b8e6479..243f8247 100644 --- a/win/vncconfig/resource.h +++ b/win/vncconfig/resource.h @@ -64,7 +64,6 @@ #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 diff --git a/win/vncconfig/vncconfig.cxx b/win/vncconfig/vncconfig.cxx index b1d0eef3..18045c77 100644 --- a/win/vncconfig/vncconfig.cxx +++ b/win/vncconfig/vncconfig.cxx @@ -135,7 +135,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, char* cmdLine, int cmdShow) { } 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; diff --git a/win/vncconfig/vncconfig.rc b/win/vncconfig/vncconfig.rc index ebcf7209..ae1057a8 100644 --- a/win/vncconfig/vncconfig.rc +++ b/win/vncconfig/vncconfig.rc @@ -241,20 +241,18 @@ STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CONTROL | WS_POPUP | WS_CAPTION | 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 diff --git a/win/winvnc/VNCServerService.cxx b/win/winvnc/VNCServerService.cxx index 0357677a..5656de04 100644 --- a/win/winvnc/VNCServerService.cxx +++ b/win/winvnc/VNCServerService.cxx @@ -19,9 +19,9 @@ // -=- 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> @@ -31,19 +31,25 @@ using namespace win32; 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"); } @@ -136,8 +142,8 @@ DWORD VNCServerService::serviceMain(int argc, TCHAR* argv[]) //cad request case WAIT_OBJECT_0 + 1: - if (SendSas.isValid()) - (*SendSas)(FALSE); + if (_SendSAS != NULL) + _SendSAS(FALSE); break; case WAIT_TIMEOUT: diff --git a/win/winvnc/VNCServerService.h b/win/winvnc/VNCServerService.h index a55a7294..8cb82c29 100644 --- a/win/winvnc/VNCServerService.h +++ b/win/winvnc/VNCServerService.h @@ -21,7 +21,6 @@ #include <winvnc/VNCServerWin32.h> #include <rfb_win32/Service.h> -#include <rfb_win32/DynamicFn.h> namespace winvnc { @@ -34,7 +33,6 @@ 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; |