Task #3961 - Remove Windows 95 support
This commit is contained in:
parent
1b5cdecc60
commit
3ddb7ef9e3
|
@ -37,14 +37,13 @@ CArchDaemonNone::installDaemon(const char*,
|
|||
const char*,
|
||||
const char*,
|
||||
const char*,
|
||||
const char*,
|
||||
bool)
|
||||
const char*)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CArchDaemonNone::uninstallDaemon(const char*, bool)
|
||||
CArchDaemonNone::uninstallDaemon(const char*)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
@ -58,13 +57,13 @@ CArchDaemonNone::daemonize(const char* name, DaemonFunc func)
|
|||
}
|
||||
|
||||
bool
|
||||
CArchDaemonNone::canInstallDaemon(const char*, bool)
|
||||
CArchDaemonNone::canInstallDaemon(const char*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CArchDaemonNone::isDaemonInstalled(const char*, bool)
|
||||
CArchDaemonNone::isDaemonInstalled(const char*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -39,12 +39,11 @@ public:
|
|||
const char* description,
|
||||
const char* pathname,
|
||||
const char* commandLine,
|
||||
const char* dependencies,
|
||||
bool allUsers);
|
||||
virtual void uninstallDaemon(const char* name, bool allUsers);
|
||||
const char* dependencies);
|
||||
virtual void uninstallDaemon(const char* name);
|
||||
virtual int daemonize(const char* name, DaemonFunc func);
|
||||
virtual bool canInstallDaemon(const char* name, bool allUsers);
|
||||
virtual bool isDaemonInstalled(const char* name, bool allUsers);
|
||||
virtual bool canInstallDaemon(const char* name);
|
||||
virtual bool isDaemonInstalled(const char* name);
|
||||
virtual void installDaemon();
|
||||
virtual void uninstallDaemon();
|
||||
virtual std::string commandLine() const;
|
||||
|
|
|
@ -51,14 +51,13 @@ public:
|
|||
const char* description,
|
||||
const char* pathname,
|
||||
const char* commandLine,
|
||||
const char* dependencies,
|
||||
bool allUsers) = 0;
|
||||
const char* dependencies) = 0;
|
||||
|
||||
//! Uninstall daemon
|
||||
/*!
|
||||
Uninstall a daemon. Throws an \c XArchDaemon on failure.
|
||||
*/
|
||||
virtual void uninstallDaemon(const char* name, bool allUsers) = 0;
|
||||
virtual void uninstallDaemon(const char* name) = 0;
|
||||
|
||||
//! Install daemon
|
||||
/*!
|
||||
|
@ -109,13 +108,13 @@ public:
|
|||
may still fail. This method ignores whether or not the
|
||||
service is already installed.
|
||||
*/
|
||||
virtual bool canInstallDaemon(const char* name, bool allUsers) = 0;
|
||||
virtual bool canInstallDaemon(const char* name) = 0;
|
||||
|
||||
//! Check if the daemon is installed
|
||||
/*!
|
||||
Returns true iff the daemon is installed.
|
||||
*/
|
||||
virtual bool isDaemonInstalled(const char* name, bool allUsers) = 0;
|
||||
virtual bool isDaemonInstalled(const char* name) = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -45,17 +45,12 @@ int
|
|||
CArchDaemonWindows::runDaemon(RunFunc runFunc)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
|
||||
return s_daemon->doRunDaemon(runFunc);
|
||||
}
|
||||
|
||||
void
|
||||
CArchDaemonWindows::daemonRunning(bool running)
|
||||
{
|
||||
// if s_daemon is NULL we assume we're running on the windows
|
||||
// 95 family and we just ignore this call so the caller doesn't
|
||||
// have to go through the trouble of not calling it on the
|
||||
// windows 95 family.
|
||||
if (s_daemon != NULL) {
|
||||
s_daemon->doDaemonRunning(running);
|
||||
}
|
||||
|
@ -75,13 +70,8 @@ CArchDaemonWindows::getDaemonQuitMessage()
|
|||
void
|
||||
CArchDaemonWindows::daemonFailed(int result)
|
||||
{
|
||||
// if s_daemon is NULL we assume we're running on the windows
|
||||
// 95 family and we just ignore this call so the caller doesn't
|
||||
// have to go through the trouble of not calling it on the
|
||||
// windows 95 family.
|
||||
if (s_daemon != NULL) {
|
||||
throw XArchDaemonRunFailed(result);
|
||||
}
|
||||
assert(s_daemon != NULL);
|
||||
throw XArchDaemonRunFailed(result);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -89,195 +79,146 @@ CArchDaemonWindows::installDaemon(const char* name,
|
|||
const char* description,
|
||||
const char* pathname,
|
||||
const char* commandLine,
|
||||
const char* dependencies,
|
||||
bool allUsers)
|
||||
const char* dependencies)
|
||||
{
|
||||
// if not for all users then use the user's autostart registry.
|
||||
// key. if windows 95 family then use windows 95 services key.
|
||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
||||
// open registry
|
||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
||||
open95ServicesKey() : openUserStartupKey();
|
||||
if (key == NULL) {
|
||||
// can't open key
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// construct entry
|
||||
std::string value;
|
||||
value += "\"";
|
||||
value += pathname;
|
||||
value += "\" ";
|
||||
value += commandLine;
|
||||
|
||||
// install entry
|
||||
CArchMiscWindows::setValue(key, name, value);
|
||||
|
||||
// clean up
|
||||
CArchMiscWindows::closeKey(key);
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// windows NT family services
|
||||
// create the service
|
||||
SC_HANDLE service = CreateService(
|
||||
mgr,
|
||||
name,
|
||||
name,
|
||||
0,
|
||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
pathname,
|
||||
NULL,
|
||||
NULL,
|
||||
dependencies,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (service == NULL) {
|
||||
// can't create service
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_EXISTS) {
|
||||
CloseServiceHandle(mgr);
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// create the service
|
||||
SC_HANDLE service = CreateService(mgr,
|
||||
name,
|
||||
name,
|
||||
0,
|
||||
SERVICE_WIN32_OWN_PROCESS |
|
||||
SERVICE_INTERACTIVE_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
pathname,
|
||||
NULL,
|
||||
NULL,
|
||||
dependencies,
|
||||
NULL,
|
||||
NULL);
|
||||
if (service == NULL) {
|
||||
// can't create service
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_EXISTS) {
|
||||
CloseServiceHandle(mgr);
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// done with service (but only try to close if not null)
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
|
||||
// done with manager
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
// open the registry key for this service
|
||||
HKEY key = openNTServicesKey();
|
||||
key = CArchMiscWindows::addKey(key, name);
|
||||
if (key == NULL) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
try {
|
||||
uninstallDaemon(name, allUsers);
|
||||
}
|
||||
catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
|
||||
// set the description
|
||||
CArchMiscWindows::setValue(key, _T("Description"), description);
|
||||
|
||||
// set command line
|
||||
key = CArchMiscWindows::addKey(key, _T("Parameters"));
|
||||
if (key == NULL) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
CArchMiscWindows::closeKey(key);
|
||||
try {
|
||||
uninstallDaemon(name, allUsers);
|
||||
}
|
||||
catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
CArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);
|
||||
|
||||
// done with registry
|
||||
CArchMiscWindows::closeKey(key);
|
||||
// done with service (but only try to close if not null)
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
|
||||
// done with manager
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
// open the registry key for this service
|
||||
HKEY key = openNTServicesKey();
|
||||
key = CArchMiscWindows::addKey(key, name);
|
||||
if (key == NULL) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
try {
|
||||
uninstallDaemon(name);
|
||||
}
|
||||
catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
|
||||
// set the description
|
||||
CArchMiscWindows::setValue(key, _T("Description"), description);
|
||||
|
||||
// set command line
|
||||
key = CArchMiscWindows::addKey(key, _T("Parameters"));
|
||||
if (key == NULL) {
|
||||
// can't open key
|
||||
DWORD err = GetLastError();
|
||||
CArchMiscWindows::closeKey(key);
|
||||
try {
|
||||
uninstallDaemon(name);
|
||||
}
|
||||
catch (...) {
|
||||
// ignore
|
||||
}
|
||||
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
CArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);
|
||||
|
||||
// done with registry
|
||||
CArchMiscWindows::closeKey(key);
|
||||
}
|
||||
|
||||
void
|
||||
CArchDaemonWindows::uninstallDaemon(const char* name, bool allUsers)
|
||||
CArchDaemonWindows::uninstallDaemon(const char* name)
|
||||
{
|
||||
// if not for all users then use the user's autostart registry.
|
||||
// key. if windows 95 family then use windows 95 services key.
|
||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
||||
// open registry
|
||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
||||
open95ServicesKey() : openUserStartupKey();
|
||||
if (key == NULL) {
|
||||
// can't open key. daemon is probably not installed.
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// remove entry
|
||||
CArchMiscWindows::deleteValue(key, name);
|
||||
|
||||
// clean up
|
||||
// remove parameters for this service. ignore failures.
|
||||
HKEY key = openNTServicesKey();
|
||||
key = CArchMiscWindows::openKey(key, name);
|
||||
if (key != NULL) {
|
||||
CArchMiscWindows::deleteKey(key, _T("Parameters"));
|
||||
CArchMiscWindows::closeKey(key);
|
||||
}
|
||||
|
||||
// windows NT family services
|
||||
else {
|
||||
// remove parameters for this service. ignore failures.
|
||||
HKEY key = openNTServicesKey();
|
||||
key = CArchMiscWindows::openKey(key, name);
|
||||
if (key != NULL) {
|
||||
CArchMiscWindows::deleteKey(key, _T("Parameters"));
|
||||
CArchMiscWindows::closeKey(key);
|
||||
}
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
// can't open service manager
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
// open the service. oddly, you must open a service to delete it.
|
||||
SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
|
||||
if (service == NULL) {
|
||||
DWORD err = GetLastError();
|
||||
CloseServiceHandle(mgr);
|
||||
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
}
|
||||
|
||||
// stop the service. we don't care if we fail.
|
||||
SERVICE_STATUS status;
|
||||
ControlService(service, SERVICE_CONTROL_STOP, &status);
|
||||
|
||||
// delete the service
|
||||
const bool okay = (DeleteService(service) == 0);
|
||||
const DWORD err = GetLastError();
|
||||
|
||||
// clean up
|
||||
CloseServiceHandle(service);
|
||||
// open the service. oddly, you must open a service to delete it.
|
||||
SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
|
||||
if (service == NULL) {
|
||||
DWORD err = GetLastError();
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
// give windows a chance to remove the service before
|
||||
// we check if it still exists.
|
||||
ARCH->sleep(1);
|
||||
|
||||
// handle failure. ignore error if service isn't installed anymore.
|
||||
if (!okay && isDaemonInstalled(name, allUsers)) {
|
||||
if (err == ERROR_SUCCESS) {
|
||||
// this seems to occur even though the uninstall was successful.
|
||||
// it could be a timing issue, i.e., isDaemonInstalled is
|
||||
// called too soon. i've added a sleep to try and stop this.
|
||||
return;
|
||||
}
|
||||
if (err == ERROR_IO_PENDING) {
|
||||
// this seems to be a spurious error
|
||||
return;
|
||||
}
|
||||
if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
}
|
||||
|
||||
// stop the service. we don't care if we fail.
|
||||
SERVICE_STATUS status;
|
||||
ControlService(service, SERVICE_CONTROL_STOP, &status);
|
||||
|
||||
// delete the service
|
||||
const bool okay = (DeleteService(service) == 0);
|
||||
const DWORD err = GetLastError();
|
||||
|
||||
// clean up
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
// give windows a chance to remove the service before
|
||||
// we check if it still exists.
|
||||
ARCH->sleep(1);
|
||||
|
||||
// handle failure. ignore error if service isn't installed anymore.
|
||||
if (!okay && isDaemonInstalled(name)) {
|
||||
if (err == ERROR_SUCCESS) {
|
||||
// this seems to occur even though the uninstall was successful.
|
||||
// it could be a timing issue, i.e., isDaemonInstalled is
|
||||
// called too soon. i've added a sleep to try and stop this.
|
||||
return;
|
||||
}
|
||||
if (err == ERROR_IO_PENDING) {
|
||||
// this seems to be a spurious error
|
||||
return;
|
||||
}
|
||||
if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
|
||||
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,98 +228,48 @@ CArchDaemonWindows::daemonize(const char* name, DaemonFunc func)
|
|||
assert(name != NULL);
|
||||
assert(func != NULL);
|
||||
|
||||
// windows 95 family services
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
typedef DWORD (WINAPI *RegisterServiceProcessT)(DWORD, DWORD);
|
||||
// save daemon function
|
||||
m_daemonFunc = func;
|
||||
|
||||
// mark this process as a service so it's not killed when the
|
||||
// user logs off.
|
||||
HINSTANCE kernel = LoadLibrary("kernel32.dll");
|
||||
if (kernel == NULL) {
|
||||
throw XArchDaemonFailed(new XArchEvalWindows);
|
||||
}
|
||||
RegisterServiceProcessT RegisterServiceProcess =
|
||||
reinterpret_cast<RegisterServiceProcessT>(
|
||||
GetProcAddress(kernel,
|
||||
"RegisterServiceProcess"));
|
||||
if (RegisterServiceProcess == NULL) {
|
||||
// missing RegisterServiceProcess function
|
||||
DWORD err = GetLastError();
|
||||
FreeLibrary(kernel);
|
||||
throw XArchDaemonFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
if (RegisterServiceProcess(0, 1) == 0) {
|
||||
// RegisterServiceProcess failed
|
||||
DWORD err = GetLastError();
|
||||
FreeLibrary(kernel);
|
||||
throw XArchDaemonFailed(new XArchEvalWindows(err));
|
||||
}
|
||||
FreeLibrary(kernel);
|
||||
|
||||
// now simply call the daemon function
|
||||
return func(1, &name);
|
||||
}
|
||||
|
||||
// windows NT family services
|
||||
else {
|
||||
// save daemon function
|
||||
m_daemonFunc = func;
|
||||
|
||||
// construct the service entry
|
||||
SERVICE_TABLE_ENTRY entry[2];
|
||||
entry[0].lpServiceName = const_cast<char*>(name);
|
||||
entry[0].lpServiceProc = &CArchDaemonWindows::serviceMainEntry;
|
||||
entry[1].lpServiceName = NULL;
|
||||
entry[1].lpServiceProc = NULL;
|
||||
|
||||
// hook us up to the service control manager. this won't return
|
||||
// (if successful) until the processes have terminated.
|
||||
s_daemon = this;
|
||||
if (StartServiceCtrlDispatcher(entry) == 0) {
|
||||
// StartServiceCtrlDispatcher failed
|
||||
s_daemon = NULL;
|
||||
throw XArchDaemonFailed(new XArchEvalWindows);
|
||||
}
|
||||
// construct the service entry
|
||||
SERVICE_TABLE_ENTRY entry[2];
|
||||
entry[0].lpServiceName = const_cast<char*>(name);
|
||||
entry[0].lpServiceProc = &CArchDaemonWindows::serviceMainEntry;
|
||||
entry[1].lpServiceName = NULL;
|
||||
entry[1].lpServiceProc = NULL;
|
||||
|
||||
// hook us up to the service control manager. this won't return
|
||||
// (if successful) until the processes have terminated.
|
||||
s_daemon = this;
|
||||
if (StartServiceCtrlDispatcher(entry) == 0) {
|
||||
// StartServiceCtrlDispatcher failed
|
||||
s_daemon = NULL;
|
||||
return m_daemonResult;
|
||||
throw XArchDaemonFailed(new XArchEvalWindows);
|
||||
}
|
||||
|
||||
s_daemon = NULL;
|
||||
return m_daemonResult;
|
||||
}
|
||||
|
||||
bool
|
||||
CArchDaemonWindows::canInstallDaemon(const char* /*name*/, bool allUsers)
|
||||
CArchDaemonWindows::canInstallDaemon(const char* /*name*/)
|
||||
{
|
||||
// if not for all users then use the user's autostart registry.
|
||||
// key. if windows 95 family then use windows 95 services key.
|
||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
||||
// check if we can open the registry key
|
||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
||||
open95ServicesKey() : openUserStartupKey();
|
||||
CArchMiscWindows::closeKey(key);
|
||||
return (key != NULL);
|
||||
// check if we can open service manager for write
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
return false;
|
||||
}
|
||||
CloseServiceHandle(mgr);
|
||||
|
||||
// windows NT family services
|
||||
else {
|
||||
// check if we can open service manager for write
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||
if (mgr == NULL) {
|
||||
return false;
|
||||
}
|
||||
CloseServiceHandle(mgr);
|
||||
// check if we can open the registry key
|
||||
HKEY key = openNTServicesKey();
|
||||
CArchMiscWindows::closeKey(key);
|
||||
|
||||
// check if we can open the registry key
|
||||
HKEY key = openNTServicesKey();
|
||||
// key = CArchMiscWindows::addKey(key, name);
|
||||
// key = CArchMiscWindows::addKey(key, _T("Parameters"));
|
||||
CArchMiscWindows::closeKey(key);
|
||||
|
||||
return (key != NULL);
|
||||
}
|
||||
return (key != NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
CArchDaemonWindows::isDaemonInstalled(const char* name, bool allUsers)
|
||||
CArchDaemonWindows::isDaemonInstalled(const char* name)
|
||||
{
|
||||
// open service manager
|
||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||
|
@ -411,36 +302,6 @@ CArchDaemonWindows::openNTServicesKey()
|
|||
return CArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames);
|
||||
}
|
||||
|
||||
HKEY
|
||||
CArchDaemonWindows::open95ServicesKey()
|
||||
{
|
||||
static const char* s_keyNames[] = {
|
||||
_T("Software"),
|
||||
_T("Microsoft"),
|
||||
_T("Windows"),
|
||||
_T("CurrentVersion"),
|
||||
_T("RunServices"),
|
||||
NULL
|
||||
};
|
||||
|
||||
return CArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames);
|
||||
}
|
||||
|
||||
HKEY
|
||||
CArchDaemonWindows::openUserStartupKey()
|
||||
{
|
||||
static const char* s_keyNames[] = {
|
||||
_T("Software"),
|
||||
_T("Microsoft"),
|
||||
_T("Windows"),
|
||||
_T("CurrentVersion"),
|
||||
_T("Run"),
|
||||
NULL
|
||||
};
|
||||
|
||||
return CArchMiscWindows::addKey(HKEY_CURRENT_USER, s_keyNames);
|
||||
}
|
||||
|
||||
bool
|
||||
CArchDaemonWindows::isRunState(DWORD state)
|
||||
{
|
||||
|
@ -817,7 +678,7 @@ void
|
|||
CArchDaemonWindows::installDaemon()
|
||||
{
|
||||
// install default daemon if not already installed.
|
||||
if (!isDaemonInstalled(DEFAULT_DAEMON_NAME, true)) {
|
||||
if (!isDaemonInstalled(DEFAULT_DAEMON_NAME)) {
|
||||
char path[MAX_PATH];
|
||||
GetModuleFileName(CArchMiscWindows::instanceWin32(), path, MAX_PATH);
|
||||
|
||||
|
@ -827,7 +688,7 @@ CArchDaemonWindows::installDaemon()
|
|||
ss << path;
|
||||
ss << '"';
|
||||
|
||||
installDaemon(DEFAULT_DAEMON_NAME, DEFAULT_DAEMON_INFO, ss.str().c_str(), "", "", true);
|
||||
installDaemon(DEFAULT_DAEMON_NAME, DEFAULT_DAEMON_INFO, ss.str().c_str(), "", "");
|
||||
}
|
||||
|
||||
start(DEFAULT_DAEMON_NAME);
|
||||
|
@ -837,15 +698,15 @@ void
|
|||
CArchDaemonWindows::uninstallDaemon()
|
||||
{
|
||||
// remove legacy services if installed.
|
||||
if (isDaemonInstalled(LEGACY_SERVER_DAEMON_NAME, true)) {
|
||||
uninstallDaemon(LEGACY_SERVER_DAEMON_NAME, true);
|
||||
if (isDaemonInstalled(LEGACY_SERVER_DAEMON_NAME)) {
|
||||
uninstallDaemon(LEGACY_SERVER_DAEMON_NAME);
|
||||
}
|
||||
if (isDaemonInstalled(LEGACY_CLIENT_DAEMON_NAME, true)) {
|
||||
uninstallDaemon(LEGACY_CLIENT_DAEMON_NAME, true);
|
||||
if (isDaemonInstalled(LEGACY_CLIENT_DAEMON_NAME)) {
|
||||
uninstallDaemon(LEGACY_CLIENT_DAEMON_NAME);
|
||||
}
|
||||
|
||||
// remove new service if installed.
|
||||
if (isDaemonInstalled(DEFAULT_DAEMON_NAME, true)) {
|
||||
uninstallDaemon(DEFAULT_DAEMON_NAME, true);
|
||||
if (isDaemonInstalled(DEFAULT_DAEMON_NAME)) {
|
||||
uninstallDaemon(DEFAULT_DAEMON_NAME);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,20 +79,17 @@ public:
|
|||
const char* description,
|
||||
const char* pathname,
|
||||
const char* commandLine,
|
||||
const char* dependencies,
|
||||
bool allUsers);
|
||||
virtual void uninstallDaemon(const char* name, bool allUsers);
|
||||
const char* dependencies);
|
||||
virtual void uninstallDaemon(const char* name);
|
||||
virtual void installDaemon();
|
||||
virtual void uninstallDaemon();
|
||||
virtual int daemonize(const char* name, DaemonFunc func);
|
||||
virtual bool canInstallDaemon(const char* name, bool allUsers);
|
||||
virtual bool isDaemonInstalled(const char* name, bool allUsers);
|
||||
virtual bool canInstallDaemon(const char* name);
|
||||
virtual bool isDaemonInstalled(const char* name);
|
||||
std::string commandLine() const { return m_commandLine; }
|
||||
|
||||
private:
|
||||
static HKEY openNTServicesKey();
|
||||
static HKEY open95ServicesKey();
|
||||
static HKEY openUserStartupKey();
|
||||
|
||||
int doRunDaemon(RunFunc runFunc);
|
||||
void doDaemonRunning(bool running);
|
||||
|
|
|
@ -38,7 +38,7 @@ CArchLogWindows::~CArchLogWindows()
|
|||
void
|
||||
CArchLogWindows::openLog(const char* name)
|
||||
{
|
||||
if (m_eventLog == NULL && !CArchMiscWindows::isWindows95Family()) {
|
||||
if (m_eventLog == NULL) {
|
||||
m_eventLog = RegisterEventSource(NULL, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,53 +61,6 @@ void
|
|||
CArchMiscWindows::init()
|
||||
{
|
||||
s_dialogs = new CDialogs;
|
||||
isWindows95Family();
|
||||
}
|
||||
|
||||
bool
|
||||
CArchMiscWindows::isWindows95Family()
|
||||
{
|
||||
static bool init = false;
|
||||
static bool result = false;
|
||||
|
||||
if (!init) {
|
||||
OSVERSIONINFO version;
|
||||
version.dwOSVersionInfoSize = sizeof(version);
|
||||
if (GetVersionEx(&version) == 0) {
|
||||
// cannot determine OS; assume windows 95 family
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
result = (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
CArchMiscWindows::isWindowsModern()
|
||||
{
|
||||
static bool init = false;
|
||||
static bool result = false;
|
||||
|
||||
if (!init) {
|
||||
OSVERSIONINFO version;
|
||||
version.dwOSVersionInfoSize = sizeof(version);
|
||||
if (GetVersionEx(&version) == 0) {
|
||||
// cannot determine OS; assume not modern
|
||||
result = false;
|
||||
}
|
||||
else {
|
||||
result = ((version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
|
||||
version.dwMajorVersion == 4 &&
|
||||
version.dwMinorVersion > 0) ||
|
||||
(version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
|
||||
version.dwMajorVersion > 4));
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -51,19 +51,6 @@ public:
|
|||
//! Delete memory
|
||||
static void cleanup();
|
||||
|
||||
//! Test if windows 95, et al.
|
||||
/*!
|
||||
Returns true iff the platform is win95/98/me.
|
||||
*/
|
||||
static bool isWindows95Family();
|
||||
|
||||
//! Test if windows 95, et al.
|
||||
/*!
|
||||
Returns true iff the platform is win98 or win2k or higher (i.e.
|
||||
not windows 95 or windows NT).
|
||||
*/
|
||||
static bool isWindowsModern();
|
||||
|
||||
//! Set the application icons
|
||||
/*!
|
||||
Set the application icons.
|
||||
|
|
|
@ -83,36 +83,11 @@ CArchSystemWindows::getOSName() const
|
|||
if (info.dwMajorVersion == 5 && info.dwMinorVersion == 0) {
|
||||
return "Microsoft Windows Server 2000";
|
||||
}
|
||||
if (info.dwMajorVersion <= 4) {
|
||||
return "Microsoft Windows NT";
|
||||
}
|
||||
char buffer[100];
|
||||
sprintf(buffer, "Microsoft Windows %d.%d",
|
||||
info.dwMajorVersion, info.dwMinorVersion);
|
||||
return buffer;
|
||||
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
|
||||
if (info.szCSDVersion[1] == 'C' ||
|
||||
info.szCSDVersion[1] == 'B') {
|
||||
return "Microsoft Windows 95 OSR2";
|
||||
}
|
||||
return "Microsoft Windows 95";
|
||||
}
|
||||
if (info.dwMajorVersion == 4 && info.dwMinorVersion == 10) {
|
||||
if (info.szCSDVersion[1] == 'A') {
|
||||
return "Microsoft Windows 98 SE";
|
||||
}
|
||||
return "Microsoft Windows 98";
|
||||
}
|
||||
if (info.dwMajorVersion == 4 && info.dwMinorVersion == 90) {
|
||||
return "Microsoft Windows ME";
|
||||
}
|
||||
if (info.dwMajorVersion == 4) {
|
||||
return "Microsoft Windows unknown 95 family";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -40,11 +40,6 @@ CMSWindowsClipboard::CMSWindowsClipboard(HWND window) :
|
|||
{
|
||||
// add converters, most desired first
|
||||
m_converters.push_back(new CMSWindowsClipboardUTF16Converter);
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
// windows nt family converts to/from unicode automatically.
|
||||
// let it do so to avoid text encoding issues.
|
||||
m_converters.push_back(new CMSWindowsClipboardTextConverter);
|
||||
}
|
||||
m_converters.push_back(new CMSWindowsClipboardBitmapConverter);
|
||||
m_converters.push_back(new CMSWindowsClipboardHTMLConverter);
|
||||
}
|
||||
|
|
|
@ -98,8 +98,6 @@ CMSWindowsDesks::CMSWindowsDesks(
|
|||
IJob* updateKeys, bool stopOnDeskSwitch) :
|
||||
m_isPrimary(isPrimary),
|
||||
m_noHooks(noHooks),
|
||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
||||
m_isModernFamily(CArchMiscWindows::isWindowsModern()),
|
||||
m_isOnScreen(m_isPrimary),
|
||||
m_x(0), m_y(0),
|
||||
m_w(0), m_h(0),
|
||||
|
@ -253,26 +251,6 @@ CMSWindowsDesks::fakeKeyEvent(
|
|||
KeyButton button, UINT virtualKey,
|
||||
bool press, bool /*isAutoRepeat*/) const
|
||||
{
|
||||
// win 95 family doesn't understand handed modifier virtual keys
|
||||
if (m_is95Family) {
|
||||
switch (virtualKey) {
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
virtualKey = VK_SHIFT;
|
||||
break;
|
||||
|
||||
case VK_LCONTROL:
|
||||
case VK_RCONTROL:
|
||||
virtualKey = VK_CONTROL;
|
||||
break;
|
||||
|
||||
case VK_LMENU:
|
||||
case VK_RMENU:
|
||||
virtualKey = VK_MENU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// synthesize event
|
||||
DWORD flags = 0;
|
||||
if (((button & 0x100u) != 0)) {
|
||||
|
@ -517,51 +495,15 @@ CMSWindowsDesks::secondaryDeskProc(
|
|||
void
|
||||
CMSWindowsDesks::deskMouseMove(SInt32 x, SInt32 y) const
|
||||
{
|
||||
// motion is simple (i.e. it's on the primary monitor) if there
|
||||
// is only one monitor. it's also simple if we're not on the
|
||||
// windows 95 family since those platforms don't have a broken
|
||||
// mouse_event() function (see the comment below).
|
||||
bool simple = (!m_multimon || !m_is95Family);
|
||||
if (!simple) {
|
||||
// also simple if motion is within the primary monitor
|
||||
simple = (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) &&
|
||||
y >= 0 && y < GetSystemMetrics(SM_CYSCREEN));
|
||||
}
|
||||
|
||||
// move the mouse directly to target position if motion is simple
|
||||
if (simple) {
|
||||
// when using absolute positioning with mouse_event(),
|
||||
// the normalized device coordinates range over only
|
||||
// the primary screen.
|
||||
SInt32 w = GetSystemMetrics(SM_CXSCREEN);
|
||||
SInt32 h = GetSystemMetrics(SM_CYSCREEN);
|
||||
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||
(DWORD)((65535.0f * x) / (w - 1) + 0.5f),
|
||||
(DWORD)((65535.0f * y) / (h - 1) + 0.5f),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
// windows 98 and Me are broken. you cannot set the absolute
|
||||
// position of the mouse except on the primary monitor but you
|
||||
// can do relative moves onto any monitor. this is, in microsoft's
|
||||
// words, "by design." apparently the designers of windows 2000
|
||||
// we're a little less lazy and did it right.
|
||||
//
|
||||
// microsoft recommends in Q193003 to absolute position the cursor
|
||||
// somewhere on the primary monitor then relative move to the
|
||||
// desired location. this doesn't work for us because when the
|
||||
// user drags a scrollbar, a window, etc. it causes the dragged
|
||||
// item to jump back and forth between the position on the primary
|
||||
// monitor and the desired position. while it always ends up in
|
||||
// the right place, the effect is disconcerting.
|
||||
//
|
||||
// instead we'll get the cursor's current position and do just a
|
||||
// relative move from there to the desired position.
|
||||
else {
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
deskMouseRelativeMove(x - pos.x, y - pos.y);
|
||||
}
|
||||
// when using absolute positioning with mouse_event(),
|
||||
// the normalized device coordinates range over only
|
||||
// the primary screen.
|
||||
SInt32 w = GetSystemMetrics(SM_CXSCREEN);
|
||||
SInt32 h = GetSystemMetrics(SM_CYSCREEN);
|
||||
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||
(DWORD)((65535.0f * x) / (w - 1) + 0.5f),
|
||||
(DWORD)((65535.0f * y) / (h - 1) + 0.5f),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -993,7 +935,7 @@ CMSWindowsDesks::handleCheckDesk(const CEvent&, void*)
|
|||
|
||||
// also check if screen saver is running if on a modern OS and
|
||||
// this is the primary screen.
|
||||
if (m_isPrimary && m_isModernFamily) {
|
||||
if (m_isPrimary) {
|
||||
BOOL running;
|
||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, FALSE);
|
||||
PostThreadMessage(m_threadID, SYNERGY_MSG_SCREEN_SAVER, running, 0);
|
||||
|
@ -1003,24 +945,15 @@ CMSWindowsDesks::handleCheckDesk(const CEvent&, void*)
|
|||
HDESK
|
||||
CMSWindowsDesks::openInputDesktop()
|
||||
{
|
||||
if (m_is95Family) {
|
||||
// there's only one desktop on windows 95 et al.
|
||||
return GetThreadDesktop(GetCurrentThreadId());
|
||||
}
|
||||
else {
|
||||
return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
||||
DESKTOP_CREATEWINDOW |
|
||||
DESKTOP_HOOKCONTROL |
|
||||
GENERIC_WRITE);
|
||||
}
|
||||
return OpenInputDesktop(
|
||||
DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
||||
DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL | GENERIC_WRITE);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsDesks::closeDesktop(HDESK desk)
|
||||
{
|
||||
// on 95/98/me we don't need to close the desktop returned by
|
||||
// openInputDesktop().
|
||||
if (desk != NULL && !m_is95Family) {
|
||||
if (desk != NULL) {
|
||||
CloseDesktop(desk);
|
||||
}
|
||||
}
|
||||
|
@ -1031,9 +964,6 @@ CMSWindowsDesks::getDesktopName(HDESK desk)
|
|||
if (desk == NULL) {
|
||||
return CString();
|
||||
}
|
||||
else if (m_is95Family) {
|
||||
return "desktop";
|
||||
}
|
||||
else {
|
||||
DWORD size;
|
||||
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
||||
|
|
|
@ -251,12 +251,6 @@ private:
|
|||
// true if hooks are not to be installed (useful for debugging)
|
||||
bool m_noHooks;
|
||||
|
||||
// true if windows 95/98/me
|
||||
bool m_is95Family;
|
||||
|
||||
// true if windows 98/2k or higher (i.e. not 95/nt)
|
||||
bool m_isModernFamily;
|
||||
|
||||
// true if mouse has entered the screen
|
||||
bool m_isOnScreen;
|
||||
|
||||
|
|
|
@ -579,7 +579,6 @@ static const CWin32Modifiers s_modifiers[] =
|
|||
CMSWindowsKeyState::CMSWindowsKeyState(
|
||||
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events) :
|
||||
CKeyState(events),
|
||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
||||
m_eventTarget(eventTarget),
|
||||
m_desks(desks),
|
||||
m_keyLayout(GetKeyboardLayout(0)),
|
||||
|
@ -596,7 +595,6 @@ CMSWindowsKeyState::CMSWindowsKeyState(
|
|||
CMSWindowsKeyState::CMSWindowsKeyState(
|
||||
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events, CKeyMap& keyMap) :
|
||||
CKeyState(events, keyMap),
|
||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
||||
m_eventTarget(eventTarget),
|
||||
m_desks(desks),
|
||||
m_keyLayout(GetKeyboardLayout(0)),
|
||||
|
@ -761,10 +759,7 @@ CMSWindowsKeyState::mapKeyToVirtualKey(KeyID key) const
|
|||
void
|
||||
CMSWindowsKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState)
|
||||
{
|
||||
// handle win32 brokenness and forward to superclass
|
||||
fixKeys();
|
||||
CKeyState::onKey(button, down, newState);
|
||||
fixKeys();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -810,28 +805,22 @@ CMSWindowsKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
|
|||
bool
|
||||
CMSWindowsKeyState::fakeCtrlAltDel()
|
||||
{
|
||||
if (!m_is95Family) {
|
||||
// to fake ctrl+alt+del on the NT family we broadcast a suitable
|
||||
// hotkey to all windows on the winlogon desktop. however, the
|
||||
// current thread must be on that desktop to do the broadcast
|
||||
// and we can't switch just any thread because some own windows
|
||||
// or hooks. so start a new thread to do the real work.
|
||||
HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
|
||||
if ( hEvtSendSas ) {
|
||||
LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
|
||||
SetEvent( hEvtSendSas );
|
||||
CloseHandle( hEvtSendSas );
|
||||
}
|
||||
else {
|
||||
// to fake ctrl+alt+del on the NT family we broadcast a suitable
|
||||
// hotkey to all windows on the winlogon desktop. however, the
|
||||
// current thread must be on that desktop to do the broadcast
|
||||
// and we can't switch just any thread because some own windows
|
||||
// or hooks. so start a new thread to do the real work.
|
||||
HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
|
||||
if ( hEvtSendSas ) {
|
||||
LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
|
||||
SetEvent( hEvtSendSas );
|
||||
CloseHandle( hEvtSendSas );
|
||||
}
|
||||
else {
|
||||
CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
|
||||
cad.wait();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// simulate ctrl+alt+del
|
||||
fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt,
|
||||
virtualKeyToButton(VK_DELETE));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1006,11 +995,6 @@ CMSWindowsKeyState::getKeyMap(CKeyMap& keyMap)
|
|||
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
// add extended key only for these on 95 family
|
||||
if (m_is95Family) {
|
||||
m_buttonToVK[i | 0x100u] = vk;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_RETURN:
|
||||
|
@ -1351,77 +1335,6 @@ CMSWindowsKeyState::setWindowGroup(SInt32 group)
|
|||
Sleep(100);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsKeyState::fixKeys()
|
||||
{
|
||||
// fake key releases for the windows keys if we think they're
|
||||
// down but they're really up. we have to do this because if the
|
||||
// user presses and releases a windows key without pressing any
|
||||
// other key while it's down then the system will eat the key
|
||||
// release. if we don't detect that and synthesize the release
|
||||
// then the client won't take the usual windows key release action
|
||||
// (which on windows is to show the start menu).
|
||||
//
|
||||
// only check on the windows 95 family since the NT family reports
|
||||
// the key releases as usual.
|
||||
if (!m_is95Family) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeyButton leftButton = virtualKeyToButton(VK_LWIN);
|
||||
KeyButton rightButton = virtualKeyToButton(VK_RWIN);
|
||||
bool leftDown = isKeyDown(leftButton);
|
||||
bool rightDown = isKeyDown(rightButton);
|
||||
bool fix = (leftDown || rightDown);
|
||||
if (fix) {
|
||||
// check if either button is not really down
|
||||
bool leftAsyncDown = ((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0);
|
||||
bool rightAsyncDown = ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0);
|
||||
|
||||
if (leftAsyncDown != leftDown || rightAsyncDown != rightDown) {
|
||||
KeyModifierMask state = getActiveModifiers();
|
||||
if (!leftAsyncDown && !rightAsyncDown) {
|
||||
// no win keys are down so remove super modifier
|
||||
state &= ~KeyModifierSuper;
|
||||
}
|
||||
|
||||
// report up events
|
||||
if (leftDown && !leftAsyncDown) {
|
||||
LOG((CLOG_DEBUG1 "event: fake key release left windows key (0x%03x)", leftButton));
|
||||
CKeyState::onKey(leftButton, false, state);
|
||||
CKeyState::sendKeyEvent(m_eventTarget, false, false,
|
||||
kKeySuper_L, state, 1, leftButton);
|
||||
}
|
||||
if (rightDown && !rightAsyncDown) {
|
||||
LOG((CLOG_DEBUG1 "event: fake key release right windows key (0x%03x)", rightButton));
|
||||
CKeyState::onKey(rightButton, false, state);
|
||||
CKeyState::sendKeyEvent(m_eventTarget, false, false,
|
||||
kKeySuper_R, state, 1, rightButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fix && m_fixTimer == NULL) {
|
||||
// schedule check
|
||||
m_fixTimer = m_events->newTimer(0.1, NULL);
|
||||
m_events->adoptHandler(CEvent::kTimer, m_fixTimer,
|
||||
new TMethodEventJob<CMSWindowsKeyState>(
|
||||
this, &CMSWindowsKeyState::handleFixKeys));
|
||||
}
|
||||
else if (!fix && m_fixTimer != NULL) {
|
||||
// remove scheduled check
|
||||
m_events->removeHandler(CEvent::kTimer, m_fixTimer);
|
||||
m_events->deleteTimer(m_fixTimer);
|
||||
m_fixTimer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsKeyState::handleFixKeys(const CEvent&, void*)
|
||||
{
|
||||
fixKeys();
|
||||
}
|
||||
|
||||
KeyID
|
||||
CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
|
||||
{
|
||||
|
@ -1436,21 +1349,12 @@ CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item,
|
|||
KeyButton button, UINT virtualKey,
|
||||
PBYTE keyState, HKL hkl) const
|
||||
{
|
||||
int n;
|
||||
KeyID id;
|
||||
if (m_is95Family) {
|
||||
// XXX -- how do we get characters not in Latin-1?
|
||||
WORD ascii;
|
||||
n = ToAsciiEx(virtualKey, button, keyState, &ascii, 0, hkl);
|
||||
id = static_cast<KeyID>(ascii & 0xffu);
|
||||
}
|
||||
else {
|
||||
WCHAR unicode[2];
|
||||
n = m_ToUnicodeEx(virtualKey, button, keyState,
|
||||
unicode, sizeof(unicode) / sizeof(unicode[0]),
|
||||
0, hkl);
|
||||
id = static_cast<KeyID>(unicode[0]);
|
||||
}
|
||||
WCHAR unicode[2];
|
||||
int n = m_ToUnicodeEx(
|
||||
virtualKey, button, keyState, unicode,
|
||||
sizeof(unicode) / sizeof(unicode[0]), 0, hkl);
|
||||
KeyID id = static_cast<KeyID>(unicode[0]);
|
||||
|
||||
switch (n) {
|
||||
case -1:
|
||||
return CKeyMap::getDeadKey(id);
|
||||
|
|
|
@ -167,9 +167,6 @@ private:
|
|||
bool getGroups(GroupList&) const;
|
||||
void setWindowGroup(SInt32 group);
|
||||
|
||||
void fixKeys();
|
||||
void handleFixKeys(const CEvent&, void*);
|
||||
|
||||
KeyID getIDForKey(CKeyMap::KeyItem& item,
|
||||
KeyButton button, UINT virtualKey,
|
||||
PBYTE keyState, HKL hkl) const;
|
||||
|
@ -187,7 +184,6 @@ private:
|
|||
typedef std::map<HKL, SInt32> GroupMap;
|
||||
typedef std::map<KeyID, UINT> KeyToVKMap;
|
||||
|
||||
bool m_is95Family;
|
||||
void* m_eventTarget;
|
||||
CMSWindowsDesks* m_desks;
|
||||
HKL m_keyLayout;
|
||||
|
|
|
@ -97,7 +97,6 @@ CMSWindowsScreen::CMSWindowsScreen(
|
|||
CPlatformScreen(events),
|
||||
m_isPrimary(isPrimary),
|
||||
m_noHooks(noHooks),
|
||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
||||
m_isOnScreen(m_isPrimary),
|
||||
m_class(0),
|
||||
m_x(0), m_y(0),
|
||||
|
@ -1007,22 +1006,6 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
|
|||
WPARAM wParam, LPARAM lParam, LRESULT* result)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_QUERYENDSESSION:
|
||||
if (m_is95Family) {
|
||||
*result = TRUE;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
if (m_is95Family) {
|
||||
if (wParam == TRUE && lParam == 0) {
|
||||
m_events->addEvent(CEvent(CEvent::kQuit));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
// first pass on the message
|
||||
if (m_nextClipboardWindow != NULL) {
|
||||
|
@ -1183,37 +1166,6 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
|||
KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
|
||||
button = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
|
||||
if (key != kKeyNone) {
|
||||
// fix key up. if the key isn't down according to
|
||||
// our table then we never got the key press event
|
||||
// for it. if it's not a modifier key then we'll
|
||||
// synthesize the press first. only do this on
|
||||
// the windows 95 family, which eats certain special
|
||||
// keys like alt+tab, ctrl+esc, etc.
|
||||
if (m_is95Family && !wasDown && !down) {
|
||||
switch (virtKey) {
|
||||
case VK_SHIFT:
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
case VK_CONTROL:
|
||||
case VK_LCONTROL:
|
||||
case VK_RCONTROL:
|
||||
case VK_MENU:
|
||||
case VK_LMENU:
|
||||
case VK_RMENU:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
case VK_CAPITAL:
|
||||
case VK_NUMLOCK:
|
||||
case VK_SCROLL:
|
||||
break;
|
||||
|
||||
default:
|
||||
m_keyState->sendKeyEvent(getEventTarget(),
|
||||
true, false, key, mask, 1, button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do it
|
||||
m_keyState->sendKeyEvent(getEventTarget(),
|
||||
((lParam & 0x80000000u) == 0),
|
||||
|
@ -1617,15 +1569,6 @@ CMSWindowsScreen::fixClipboardViewer()
|
|||
void
|
||||
CMSWindowsScreen::enableSpecialKeys(bool enable) const
|
||||
{
|
||||
// enable/disable ctrl+alt+del, alt+tab, etc on win95 family.
|
||||
// since the win95 family doesn't support low-level hooks, we
|
||||
// use this undocumented feature to suppress normal handling
|
||||
// of certain key combinations.
|
||||
if (m_is95Family) {
|
||||
DWORD dummy = 0;
|
||||
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,
|
||||
enable ? FALSE : TRUE, &dummy, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ButtonID
|
||||
|
@ -1865,7 +1808,7 @@ CMSWindowsScreen::getDraggingFilename()
|
|||
void
|
||||
CMSWindowsScreen::clearDraggingFilename()
|
||||
{
|
||||
LOG((CLOG_DEBUG "clearing stored dragging file name"));
|
||||
LOG((CLOG_DEBUG1 "clearing stored dragging file name"));
|
||||
m_shellEx.clearDraggingFilename();
|
||||
}
|
||||
|
||||
|
|
|
@ -237,9 +237,6 @@ private:
|
|||
// true if hooks are not to be installed (useful for debugging)
|
||||
bool m_noHooks;
|
||||
|
||||
// true if windows 95/98/me
|
||||
bool m_is95Family;
|
||||
|
||||
// true if mouse has entered the screen
|
||||
bool m_isOnScreen;
|
||||
|
||||
|
|
|
@ -52,25 +52,6 @@ CMSWindowsScreenSaver::CMSWindowsScreenSaver() :
|
|||
m_threadID(0),
|
||||
m_active(false)
|
||||
{
|
||||
// detect OS
|
||||
m_is95Family = false;
|
||||
m_is95 = false;
|
||||
m_isNT = false;
|
||||
OSVERSIONINFO info;
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
if (GetVersionEx(&info)) {
|
||||
m_is95Family = (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
||||
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT &&
|
||||
info.dwMajorVersion <= 4) {
|
||||
m_isNT = true;
|
||||
}
|
||||
else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
|
||||
info.dwMajorVersion == 4 &&
|
||||
info.dwMinorVersion == 0) {
|
||||
m_is95 = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check if screen saver is enabled
|
||||
SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0);
|
||||
}
|
||||
|
@ -104,38 +85,19 @@ CMSWindowsScreenSaver::checkStarted(UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
m_wParam = wParam;
|
||||
m_lParam = lParam;
|
||||
|
||||
// we handle the screen saver differently for the windows
|
||||
// 95 and nt families.
|
||||
if (m_is95Family) {
|
||||
// on windows 95 we wait for the screen saver process
|
||||
// to terminate. get the process.
|
||||
DWORD processID = findScreenSaver();
|
||||
HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, processID);
|
||||
if (process == NULL) {
|
||||
// didn't start
|
||||
LOG((CLOG_DEBUG2 "can't open screen saver process"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// watch for the process to exit
|
||||
watchProcess(process);
|
||||
}
|
||||
else {
|
||||
// on the windows nt family we wait for the desktop to
|
||||
// change until it's neither the Screen-Saver desktop
|
||||
// nor a desktop we can't open (the login desktop).
|
||||
// since windows will send the request-to-start-screen-
|
||||
// saver message even when the screen saver is disabled
|
||||
// we first check that the screen saver is indeed active
|
||||
// before watching for it to stop.
|
||||
if (!isActive()) {
|
||||
LOG((CLOG_DEBUG2 "can't open screen saver desktop"));
|
||||
return false;
|
||||
}
|
||||
|
||||
watchDesktop();
|
||||
// on the windows nt family we wait for the desktop to
|
||||
// change until it's neither the Screen-Saver desktop
|
||||
// nor a desktop we can't open (the login desktop).
|
||||
// since windows will send the request-to-start-screen-
|
||||
// saver message even when the screen saver is disabled
|
||||
// we first check that the screen saver is indeed active
|
||||
// before watching for it to stop.
|
||||
if (!isActive()) {
|
||||
LOG((CLOG_DEBUG2 "can't open screen saver desktop"));
|
||||
return false;
|
||||
}
|
||||
|
||||
watchDesktop();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -193,16 +155,15 @@ void
|
|||
CMSWindowsScreenSaver::deactivate()
|
||||
{
|
||||
bool killed = false;
|
||||
if (!m_is95Family) {
|
||||
// NT runs screen saver in another desktop
|
||||
HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE,
|
||||
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
|
||||
if (desktop != NULL) {
|
||||
EnumDesktopWindows(desktop,
|
||||
&CMSWindowsScreenSaver::killScreenSaverFunc,
|
||||
reinterpret_cast<LPARAM>(&killed));
|
||||
CloseDesktop(desktop);
|
||||
}
|
||||
|
||||
// NT runs screen saver in another desktop
|
||||
HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE,
|
||||
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
|
||||
if (desktop != NULL) {
|
||||
EnumDesktopWindows(desktop,
|
||||
&CMSWindowsScreenSaver::killScreenSaverFunc,
|
||||
reinterpret_cast<LPARAM>(&killed));
|
||||
CloseDesktop(desktop);
|
||||
}
|
||||
|
||||
// if above failed or wasn't tried, try the windows 95 way
|
||||
|
@ -232,68 +193,9 @@ CMSWindowsScreenSaver::deactivate()
|
|||
bool
|
||||
CMSWindowsScreenSaver::isActive() const
|
||||
{
|
||||
if (m_is95) {
|
||||
return (FindWindow("WindowsScreenSaverClass", NULL) != NULL);
|
||||
}
|
||||
else if (m_isNT) {
|
||||
// screen saver runs on a separate desktop
|
||||
HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE, MAXIMUM_ALLOWED);
|
||||
if (desktop == NULL && GetLastError() != ERROR_ACCESS_DENIED) {
|
||||
// desktop doesn't exist so screen saver is not running
|
||||
return false;
|
||||
}
|
||||
|
||||
// desktop exists. this should indicate that the screen saver
|
||||
// is running but an OS bug can cause a valid handle to be
|
||||
// returned even if the screen saver isn't running (Q230117).
|
||||
// we'll try to enumerate the windows on the desktop and, if
|
||||
// there are any, we assume the screen saver is running. (note
|
||||
// that if we don't have permission to enumerate then we'll
|
||||
// assume that the screen saver is not running.) that'd be
|
||||
// easy enough except there's another OS bug (Q198590) that can
|
||||
// cause EnumDesktopWindows() to enumerate the windows of
|
||||
// another desktop if the requested desktop has no windows. to
|
||||
// work around that we have to verify that the enumerated
|
||||
// windows are, in fact, on the expected desktop.
|
||||
CFindScreenSaverInfo info;
|
||||
info.m_desktop = desktop;
|
||||
info.m_window = NULL;
|
||||
EnumDesktopWindows(desktop,
|
||||
&CMSWindowsScreenSaver::findScreenSaverFunc,
|
||||
reinterpret_cast<LPARAM>(&info));
|
||||
|
||||
// done with desktop
|
||||
CloseDesktop(desktop);
|
||||
|
||||
// screen saver is running if a window was found
|
||||
return (info.m_window != NULL);
|
||||
}
|
||||
else {
|
||||
BOOL running;
|
||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||
return (running != FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
CMSWindowsScreenSaver::findScreenSaverFunc(HWND hwnd, LPARAM arg)
|
||||
{
|
||||
CFindScreenSaverInfo* info = reinterpret_cast<CFindScreenSaverInfo*>(arg);
|
||||
|
||||
if (info->m_desktop != NULL) {
|
||||
DWORD threadID = GetWindowThreadProcessId(hwnd, NULL);
|
||||
HDESK desktop = GetThreadDesktop(threadID);
|
||||
if (desktop != NULL && desktop != info->m_desktop) {
|
||||
// stop enumerating -- wrong desktop
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// found a window
|
||||
info->m_window = hwnd;
|
||||
|
||||
// don't need to enumerate further
|
||||
return FALSE;
|
||||
BOOL running;
|
||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||
return (running != FALSE);
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
|
@ -309,23 +211,6 @@ CMSWindowsScreenSaver::killScreenSaverFunc(HWND hwnd, LPARAM arg)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD
|
||||
CMSWindowsScreenSaver::findScreenSaver()
|
||||
{
|
||||
// try windows 95 way
|
||||
HWND hwnd = FindWindow("WindowsScreenSaverClass", NULL);
|
||||
|
||||
// get process ID of process that owns the window, if found
|
||||
if (hwnd != NULL) {
|
||||
DWORD processID;
|
||||
GetWindowThreadProcessId(hwnd, &processID);
|
||||
return processID;
|
||||
}
|
||||
|
||||
// not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreenSaver::watchDesktop()
|
||||
{
|
||||
|
@ -382,41 +267,10 @@ CMSWindowsScreenSaver::watchDesktopThread(void*)
|
|||
// wait a bit
|
||||
ARCH->sleep(0.2);
|
||||
|
||||
if (m_isNT) {
|
||||
// get current desktop
|
||||
HDESK desk = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
||||
if (desk == NULL) {
|
||||
// can't open desktop so keep waiting
|
||||
continue;
|
||||
}
|
||||
|
||||
// get current desktop name length
|
||||
DWORD size;
|
||||
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
||||
|
||||
// allocate more space for the name, if necessary
|
||||
if (size > reserved) {
|
||||
reserved = size;
|
||||
name = (TCHAR*)alloca(reserved + sizeof(TCHAR));
|
||||
}
|
||||
|
||||
// get current desktop name
|
||||
GetUserObjectInformation(desk, UOI_NAME, name, size, &size);
|
||||
CloseDesktop(desk);
|
||||
|
||||
// compare name to screen saver desktop name
|
||||
if (_tcsicmp(name, TEXT("Screen-saver")) == 0) {
|
||||
// still the screen saver desktop so keep waiting
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 2000/XP have a sane way to detect a runnin screensaver.
|
||||
BOOL running;
|
||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||
if (running) {
|
||||
continue;
|
||||
}
|
||||
BOOL running;
|
||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||
if (running) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// send screen saver deactivation message
|
||||
|
@ -452,12 +306,11 @@ CMSWindowsScreenSaver::setSecure(bool secure, bool saveSecureAsInt)
|
|||
return;
|
||||
}
|
||||
|
||||
const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT;
|
||||
if (saveSecureAsInt) {
|
||||
CArchMiscWindows::setValue(hkey, isSecure, secure ? 1 : 0);
|
||||
CArchMiscWindows::setValue(hkey, g_isSecureNT, secure ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
CArchMiscWindows::setValue(hkey, isSecure, secure ? "1" : "0");
|
||||
CArchMiscWindows::setValue(hkey, g_isSecureNT, secure ? "1" : "0");
|
||||
}
|
||||
|
||||
CArchMiscWindows::closeKey(hkey);
|
||||
|
@ -476,15 +329,14 @@ CMSWindowsScreenSaver::isSecure(bool* wasSecureFlagAnInt) const
|
|||
// get the value. the value may be an int or a string, depending
|
||||
// on the version of windows.
|
||||
bool result;
|
||||
const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT;
|
||||
switch (CArchMiscWindows::typeOfValue(hkey, isSecure)) {
|
||||
switch (CArchMiscWindows::typeOfValue(hkey, g_isSecureNT)) {
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
|
||||
case CArchMiscWindows::kUINT: {
|
||||
DWORD value =
|
||||
CArchMiscWindows::readValueInt(hkey, isSecure);
|
||||
CArchMiscWindows::readValueInt(hkey, g_isSecureNT);
|
||||
*wasSecureFlagAnInt = true;
|
||||
result = (value != 0);
|
||||
break;
|
||||
|
@ -492,7 +344,7 @@ CMSWindowsScreenSaver::isSecure(bool* wasSecureFlagAnInt) const
|
|||
|
||||
case CArchMiscWindows::kSTRING: {
|
||||
std::string value =
|
||||
CArchMiscWindows::readValueString(hkey, isSecure);
|
||||
CArchMiscWindows::readValueString(hkey, g_isSecureNT);
|
||||
*wasSecureFlagAnInt = false;
|
||||
result = (value != "0");
|
||||
break;
|
||||
|
|
|
@ -60,10 +60,8 @@ private:
|
|||
HWND m_window;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK findScreenSaverFunc(HWND hwnd, LPARAM lParam);
|
||||
static BOOL CALLBACK killScreenSaverFunc(HWND hwnd, LPARAM lParam);
|
||||
|
||||
DWORD findScreenSaver();
|
||||
void watchDesktop();
|
||||
void watchProcess(HANDLE process);
|
||||
void unwatchProcess();
|
||||
|
@ -74,9 +72,6 @@ private:
|
|||
bool isSecure(bool* wasSecureAnInt) const;
|
||||
|
||||
private:
|
||||
bool m_is95Family;
|
||||
bool m_is95;
|
||||
bool m_isNT;
|
||||
BOOL m_wasEnabled;
|
||||
bool m_wasSecure;
|
||||
bool m_wasSecureAnInt;
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
*/
|
||||
|
||||
#include "synergy/win32/AppUtilWindows.h"
|
||||
#include "common/Version.h"
|
||||
#include "base/Log.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include "synergy/App.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "platform/MSWindowsScreen.h"
|
||||
#include "synergy/XSynergy.h"
|
||||
#include "arch/IArchTaskBarReceiver.h"
|
||||
#include "synergy/Screen.h"
|
||||
#include "synergy/ArgsBase.h"
|
||||
#include "synergy/App.h"
|
||||
#include "synergy/XSynergy.h"
|
||||
#include "platform/MSWindowsScreen.h"
|
||||
#include "arch/win32/XArchWindows.h"
|
||||
#include "arch/win32/ArchMiscWindows.h"
|
||||
#include "arch/IArchTaskBarReceiver.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/log_outputters.h"
|
||||
#include "base/IEventQueue.h"
|
||||
#include "base/Event.h"
|
||||
#include "base/EventQueue.h"
|
||||
#include "common/Version.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
@ -156,6 +156,15 @@ CAppUtilWindows::beforeAppExit()
|
|||
int
|
||||
CAppUtilWindows::run(int argc, char** argv)
|
||||
{
|
||||
OSVERSIONINFO osvi;
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osvi);
|
||||
|
||||
if (osvi.dwMajorVersion < 5 || (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion < 1)) {
|
||||
throw std::runtime_error("synergy only supports windows xp and above.");
|
||||
}
|
||||
|
||||
// record window instance for tray icon, etc
|
||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||
|
||||
|
|
Loading…
Reference in New Issue