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*,
|
||||||
const char*,
|
const char*,
|
||||||
const char*,
|
const char*)
|
||||||
bool)
|
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchDaemonNone::uninstallDaemon(const char*, bool)
|
CArchDaemonNone::uninstallDaemon(const char*)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
@ -58,13 +57,13 @@ CArchDaemonNone::daemonize(const char* name, DaemonFunc func)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CArchDaemonNone::canInstallDaemon(const char*, bool)
|
CArchDaemonNone::canInstallDaemon(const char*)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CArchDaemonNone::isDaemonInstalled(const char*, bool)
|
CArchDaemonNone::isDaemonInstalled(const char*)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,11 @@ public:
|
||||||
const char* description,
|
const char* description,
|
||||||
const char* pathname,
|
const char* pathname,
|
||||||
const char* commandLine,
|
const char* commandLine,
|
||||||
const char* dependencies,
|
const char* dependencies);
|
||||||
bool allUsers);
|
virtual void uninstallDaemon(const char* name);
|
||||||
virtual void uninstallDaemon(const char* name, bool allUsers);
|
|
||||||
virtual int daemonize(const char* name, DaemonFunc func);
|
virtual int daemonize(const char* name, DaemonFunc func);
|
||||||
virtual bool canInstallDaemon(const char* name, bool allUsers);
|
virtual bool canInstallDaemon(const char* name);
|
||||||
virtual bool isDaemonInstalled(const char* name, bool allUsers);
|
virtual bool isDaemonInstalled(const char* name);
|
||||||
virtual void installDaemon();
|
virtual void installDaemon();
|
||||||
virtual void uninstallDaemon();
|
virtual void uninstallDaemon();
|
||||||
virtual std::string commandLine() const;
|
virtual std::string commandLine() const;
|
||||||
|
|
|
@ -51,14 +51,13 @@ public:
|
||||||
const char* description,
|
const char* description,
|
||||||
const char* pathname,
|
const char* pathname,
|
||||||
const char* commandLine,
|
const char* commandLine,
|
||||||
const char* dependencies,
|
const char* dependencies) = 0;
|
||||||
bool allUsers) = 0;
|
|
||||||
|
|
||||||
//! Uninstall daemon
|
//! Uninstall daemon
|
||||||
/*!
|
/*!
|
||||||
Uninstall a daemon. Throws an \c XArchDaemon on failure.
|
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
|
//! Install daemon
|
||||||
/*!
|
/*!
|
||||||
|
@ -109,13 +108,13 @@ public:
|
||||||
may still fail. This method ignores whether or not the
|
may still fail. This method ignores whether or not the
|
||||||
service is already installed.
|
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
|
//! Check if the daemon is installed
|
||||||
/*!
|
/*!
|
||||||
Returns true iff 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)
|
CArchDaemonWindows::runDaemon(RunFunc runFunc)
|
||||||
{
|
{
|
||||||
assert(s_daemon != NULL);
|
assert(s_daemon != NULL);
|
||||||
|
|
||||||
return s_daemon->doRunDaemon(runFunc);
|
return s_daemon->doRunDaemon(runFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchDaemonWindows::daemonRunning(bool running)
|
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) {
|
if (s_daemon != NULL) {
|
||||||
s_daemon->doDaemonRunning(running);
|
s_daemon->doDaemonRunning(running);
|
||||||
}
|
}
|
||||||
|
@ -75,13 +70,8 @@ CArchDaemonWindows::getDaemonQuitMessage()
|
||||||
void
|
void
|
||||||
CArchDaemonWindows::daemonFailed(int result)
|
CArchDaemonWindows::daemonFailed(int result)
|
||||||
{
|
{
|
||||||
// if s_daemon is NULL we assume we're running on the windows
|
assert(s_daemon != NULL);
|
||||||
// 95 family and we just ignore this call so the caller doesn't
|
throw XArchDaemonRunFailed(result);
|
||||||
// have to go through the trouble of not calling it on the
|
|
||||||
// windows 95 family.
|
|
||||||
if (s_daemon != NULL) {
|
|
||||||
throw XArchDaemonRunFailed(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -89,195 +79,146 @@ CArchDaemonWindows::installDaemon(const char* name,
|
||||||
const char* description,
|
const char* description,
|
||||||
const char* pathname,
|
const char* pathname,
|
||||||
const char* commandLine,
|
const char* commandLine,
|
||||||
const char* dependencies,
|
const char* dependencies)
|
||||||
bool allUsers)
|
|
||||||
{
|
{
|
||||||
// if not for all users then use the user's autostart registry.
|
// open service manager
|
||||||
// key. if windows 95 family then use windows 95 services key.
|
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
if (mgr == NULL) {
|
||||||
// open registry
|
// can't open service manager
|
||||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
throw XArchDaemonInstallFailed(new XArchEvalWindows);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
else {
|
||||||
// open service manager
|
// done with service (but only try to close if not null)
|
||||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
CloseServiceHandle(service);
|
||||||
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 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
|
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.
|
// remove parameters for this service. ignore failures.
|
||||||
// key. if windows 95 family then use windows 95 services key.
|
HKEY key = openNTServicesKey();
|
||||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
key = CArchMiscWindows::openKey(key, name);
|
||||||
// open registry
|
if (key != NULL) {
|
||||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
CArchMiscWindows::deleteKey(key, _T("Parameters"));
|
||||||
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
|
|
||||||
CArchMiscWindows::closeKey(key);
|
CArchMiscWindows::closeKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// windows NT family services
|
// open service manager
|
||||||
else {
|
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||||
// remove parameters for this service. ignore failures.
|
if (mgr == NULL) {
|
||||||
HKEY key = openNTServicesKey();
|
// can't open service manager
|
||||||
key = CArchMiscWindows::openKey(key, name);
|
throw XArchDaemonUninstallFailed(new XArchEvalWindows);
|
||||||
if (key != NULL) {
|
}
|
||||||
CArchMiscWindows::deleteKey(key, _T("Parameters"));
|
|
||||||
CArchMiscWindows::closeKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// open service manager
|
// open the service. oddly, you must open a service to delete it.
|
||||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
|
||||||
if (mgr == NULL) {
|
if (service == NULL) {
|
||||||
// can't open service manager
|
DWORD err = GetLastError();
|
||||||
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);
|
|
||||||
CloseServiceHandle(mgr);
|
CloseServiceHandle(mgr);
|
||||||
|
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||||
// give windows a chance to remove the service before
|
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
|
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(name != NULL);
|
||||||
assert(func != NULL);
|
assert(func != NULL);
|
||||||
|
|
||||||
// windows 95 family services
|
// save daemon function
|
||||||
if (CArchMiscWindows::isWindows95Family()) {
|
m_daemonFunc = func;
|
||||||
typedef DWORD (WINAPI *RegisterServiceProcessT)(DWORD, DWORD);
|
|
||||||
|
|
||||||
// mark this process as a service so it's not killed when the
|
// construct the service entry
|
||||||
// user logs off.
|
SERVICE_TABLE_ENTRY entry[2];
|
||||||
HINSTANCE kernel = LoadLibrary("kernel32.dll");
|
entry[0].lpServiceName = const_cast<char*>(name);
|
||||||
if (kernel == NULL) {
|
entry[0].lpServiceProc = &CArchDaemonWindows::serviceMainEntry;
|
||||||
throw XArchDaemonFailed(new XArchEvalWindows);
|
entry[1].lpServiceName = NULL;
|
||||||
}
|
entry[1].lpServiceProc = NULL;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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;
|
s_daemon = NULL;
|
||||||
return m_daemonResult;
|
throw XArchDaemonFailed(new XArchEvalWindows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_daemon = NULL;
|
||||||
|
return m_daemonResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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.
|
// check if we can open service manager for write
|
||||||
// key. if windows 95 family then use windows 95 services key.
|
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
||||||
if (!allUsers || CArchMiscWindows::isWindows95Family()) {
|
if (mgr == NULL) {
|
||||||
// check if we can open the registry key
|
return false;
|
||||||
HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
|
|
||||||
open95ServicesKey() : openUserStartupKey();
|
|
||||||
CArchMiscWindows::closeKey(key);
|
|
||||||
return (key != NULL);
|
|
||||||
}
|
}
|
||||||
|
CloseServiceHandle(mgr);
|
||||||
|
|
||||||
// windows NT family services
|
// check if we can open the registry key
|
||||||
else {
|
HKEY key = openNTServicesKey();
|
||||||
// check if we can open service manager for write
|
CArchMiscWindows::closeKey(key);
|
||||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
|
|
||||||
if (mgr == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
CloseServiceHandle(mgr);
|
|
||||||
|
|
||||||
// check if we can open the registry key
|
return (key != NULL);
|
||||||
HKEY key = openNTServicesKey();
|
|
||||||
// key = CArchMiscWindows::addKey(key, name);
|
|
||||||
// key = CArchMiscWindows::addKey(key, _T("Parameters"));
|
|
||||||
CArchMiscWindows::closeKey(key);
|
|
||||||
|
|
||||||
return (key != NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CArchDaemonWindows::isDaemonInstalled(const char* name, bool allUsers)
|
CArchDaemonWindows::isDaemonInstalled(const char* name)
|
||||||
{
|
{
|
||||||
// open service manager
|
// open service manager
|
||||||
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||||
|
@ -411,36 +302,6 @@ CArchDaemonWindows::openNTServicesKey()
|
||||||
return CArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames);
|
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
|
bool
|
||||||
CArchDaemonWindows::isRunState(DWORD state)
|
CArchDaemonWindows::isRunState(DWORD state)
|
||||||
{
|
{
|
||||||
|
@ -817,7 +678,7 @@ void
|
||||||
CArchDaemonWindows::installDaemon()
|
CArchDaemonWindows::installDaemon()
|
||||||
{
|
{
|
||||||
// install default daemon if not already installed.
|
// install default daemon if not already installed.
|
||||||
if (!isDaemonInstalled(DEFAULT_DAEMON_NAME, true)) {
|
if (!isDaemonInstalled(DEFAULT_DAEMON_NAME)) {
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
GetModuleFileName(CArchMiscWindows::instanceWin32(), path, MAX_PATH);
|
GetModuleFileName(CArchMiscWindows::instanceWin32(), path, MAX_PATH);
|
||||||
|
|
||||||
|
@ -827,7 +688,7 @@ CArchDaemonWindows::installDaemon()
|
||||||
ss << path;
|
ss << path;
|
||||||
ss << '"';
|
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);
|
start(DEFAULT_DAEMON_NAME);
|
||||||
|
@ -837,15 +698,15 @@ void
|
||||||
CArchDaemonWindows::uninstallDaemon()
|
CArchDaemonWindows::uninstallDaemon()
|
||||||
{
|
{
|
||||||
// remove legacy services if installed.
|
// remove legacy services if installed.
|
||||||
if (isDaemonInstalled(LEGACY_SERVER_DAEMON_NAME, true)) {
|
if (isDaemonInstalled(LEGACY_SERVER_DAEMON_NAME)) {
|
||||||
uninstallDaemon(LEGACY_SERVER_DAEMON_NAME, true);
|
uninstallDaemon(LEGACY_SERVER_DAEMON_NAME);
|
||||||
}
|
}
|
||||||
if (isDaemonInstalled(LEGACY_CLIENT_DAEMON_NAME, true)) {
|
if (isDaemonInstalled(LEGACY_CLIENT_DAEMON_NAME)) {
|
||||||
uninstallDaemon(LEGACY_CLIENT_DAEMON_NAME, true);
|
uninstallDaemon(LEGACY_CLIENT_DAEMON_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove new service if installed.
|
// remove new service if installed.
|
||||||
if (isDaemonInstalled(DEFAULT_DAEMON_NAME, true)) {
|
if (isDaemonInstalled(DEFAULT_DAEMON_NAME)) {
|
||||||
uninstallDaemon(DEFAULT_DAEMON_NAME, true);
|
uninstallDaemon(DEFAULT_DAEMON_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,20 +79,17 @@ public:
|
||||||
const char* description,
|
const char* description,
|
||||||
const char* pathname,
|
const char* pathname,
|
||||||
const char* commandLine,
|
const char* commandLine,
|
||||||
const char* dependencies,
|
const char* dependencies);
|
||||||
bool allUsers);
|
virtual void uninstallDaemon(const char* name);
|
||||||
virtual void uninstallDaemon(const char* name, bool allUsers);
|
|
||||||
virtual void installDaemon();
|
virtual void installDaemon();
|
||||||
virtual void uninstallDaemon();
|
virtual void uninstallDaemon();
|
||||||
virtual int daemonize(const char* name, DaemonFunc func);
|
virtual int daemonize(const char* name, DaemonFunc func);
|
||||||
virtual bool canInstallDaemon(const char* name, bool allUsers);
|
virtual bool canInstallDaemon(const char* name);
|
||||||
virtual bool isDaemonInstalled(const char* name, bool allUsers);
|
virtual bool isDaemonInstalled(const char* name);
|
||||||
std::string commandLine() const { return m_commandLine; }
|
std::string commandLine() const { return m_commandLine; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static HKEY openNTServicesKey();
|
static HKEY openNTServicesKey();
|
||||||
static HKEY open95ServicesKey();
|
|
||||||
static HKEY openUserStartupKey();
|
|
||||||
|
|
||||||
int doRunDaemon(RunFunc runFunc);
|
int doRunDaemon(RunFunc runFunc);
|
||||||
void doDaemonRunning(bool running);
|
void doDaemonRunning(bool running);
|
||||||
|
|
|
@ -38,7 +38,7 @@ CArchLogWindows::~CArchLogWindows()
|
||||||
void
|
void
|
||||||
CArchLogWindows::openLog(const char* name)
|
CArchLogWindows::openLog(const char* name)
|
||||||
{
|
{
|
||||||
if (m_eventLog == NULL && !CArchMiscWindows::isWindows95Family()) {
|
if (m_eventLog == NULL) {
|
||||||
m_eventLog = RegisterEventSource(NULL, name);
|
m_eventLog = RegisterEventSource(NULL, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,53 +61,6 @@ void
|
||||||
CArchMiscWindows::init()
|
CArchMiscWindows::init()
|
||||||
{
|
{
|
||||||
s_dialogs = new CDialogs;
|
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
|
void
|
||||||
|
|
|
@ -51,19 +51,6 @@ public:
|
||||||
//! Delete memory
|
//! Delete memory
|
||||||
static void cleanup();
|
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
|
||||||
/*!
|
/*!
|
||||||
Set the application icons.
|
Set the application icons.
|
||||||
|
|
|
@ -83,36 +83,11 @@ CArchSystemWindows::getOSName() const
|
||||||
if (info.dwMajorVersion == 5 && info.dwMinorVersion == 0) {
|
if (info.dwMajorVersion == 5 && info.dwMinorVersion == 0) {
|
||||||
return "Microsoft Windows Server 2000";
|
return "Microsoft Windows Server 2000";
|
||||||
}
|
}
|
||||||
if (info.dwMajorVersion <= 4) {
|
|
||||||
return "Microsoft Windows NT";
|
|
||||||
}
|
|
||||||
char buffer[100];
|
char buffer[100];
|
||||||
sprintf(buffer, "Microsoft Windows %d.%d",
|
sprintf(buffer, "Microsoft Windows %d.%d",
|
||||||
info.dwMajorVersion, info.dwMinorVersion);
|
info.dwMajorVersion, info.dwMinorVersion);
|
||||||
return buffer;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,6 @@ CMSWindowsClipboard::CMSWindowsClipboard(HWND window) :
|
||||||
{
|
{
|
||||||
// add converters, most desired first
|
// add converters, most desired first
|
||||||
m_converters.push_back(new CMSWindowsClipboardUTF16Converter);
|
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 CMSWindowsClipboardBitmapConverter);
|
||||||
m_converters.push_back(new CMSWindowsClipboardHTMLConverter);
|
m_converters.push_back(new CMSWindowsClipboardHTMLConverter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,8 +98,6 @@ CMSWindowsDesks::CMSWindowsDesks(
|
||||||
IJob* updateKeys, bool stopOnDeskSwitch) :
|
IJob* updateKeys, bool stopOnDeskSwitch) :
|
||||||
m_isPrimary(isPrimary),
|
m_isPrimary(isPrimary),
|
||||||
m_noHooks(noHooks),
|
m_noHooks(noHooks),
|
||||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
|
||||||
m_isModernFamily(CArchMiscWindows::isWindowsModern()),
|
|
||||||
m_isOnScreen(m_isPrimary),
|
m_isOnScreen(m_isPrimary),
|
||||||
m_x(0), m_y(0),
|
m_x(0), m_y(0),
|
||||||
m_w(0), m_h(0),
|
m_w(0), m_h(0),
|
||||||
|
@ -253,26 +251,6 @@ CMSWindowsDesks::fakeKeyEvent(
|
||||||
KeyButton button, UINT virtualKey,
|
KeyButton button, UINT virtualKey,
|
||||||
bool press, bool /*isAutoRepeat*/) const
|
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
|
// synthesize event
|
||||||
DWORD flags = 0;
|
DWORD flags = 0;
|
||||||
if (((button & 0x100u) != 0)) {
|
if (((button & 0x100u) != 0)) {
|
||||||
|
@ -517,51 +495,15 @@ CMSWindowsDesks::secondaryDeskProc(
|
||||||
void
|
void
|
||||||
CMSWindowsDesks::deskMouseMove(SInt32 x, SInt32 y) const
|
CMSWindowsDesks::deskMouseMove(SInt32 x, SInt32 y) const
|
||||||
{
|
{
|
||||||
// motion is simple (i.e. it's on the primary monitor) if there
|
// when using absolute positioning with mouse_event(),
|
||||||
// is only one monitor. it's also simple if we're not on the
|
// the normalized device coordinates range over only
|
||||||
// windows 95 family since those platforms don't have a broken
|
// the primary screen.
|
||||||
// mouse_event() function (see the comment below).
|
SInt32 w = GetSystemMetrics(SM_CXSCREEN);
|
||||||
bool simple = (!m_multimon || !m_is95Family);
|
SInt32 h = GetSystemMetrics(SM_CYSCREEN);
|
||||||
if (!simple) {
|
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||||
// also simple if motion is within the primary monitor
|
(DWORD)((65535.0f * x) / (w - 1) + 0.5f),
|
||||||
simple = (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) &&
|
(DWORD)((65535.0f * y) / (h - 1) + 0.5f),
|
||||||
y >= 0 && y < GetSystemMetrics(SM_CYSCREEN));
|
0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -993,7 +935,7 @@ CMSWindowsDesks::handleCheckDesk(const CEvent&, void*)
|
||||||
|
|
||||||
// also check if screen saver is running if on a modern OS and
|
// also check if screen saver is running if on a modern OS and
|
||||||
// this is the primary screen.
|
// this is the primary screen.
|
||||||
if (m_isPrimary && m_isModernFamily) {
|
if (m_isPrimary) {
|
||||||
BOOL running;
|
BOOL running;
|
||||||
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, FALSE);
|
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, FALSE);
|
||||||
PostThreadMessage(m_threadID, SYNERGY_MSG_SCREEN_SAVER, running, 0);
|
PostThreadMessage(m_threadID, SYNERGY_MSG_SCREEN_SAVER, running, 0);
|
||||||
|
@ -1003,24 +945,15 @@ CMSWindowsDesks::handleCheckDesk(const CEvent&, void*)
|
||||||
HDESK
|
HDESK
|
||||||
CMSWindowsDesks::openInputDesktop()
|
CMSWindowsDesks::openInputDesktop()
|
||||||
{
|
{
|
||||||
if (m_is95Family) {
|
return OpenInputDesktop(
|
||||||
// there's only one desktop on windows 95 et al.
|
DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
||||||
return GetThreadDesktop(GetCurrentThreadId());
|
DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL | GENERIC_WRITE);
|
||||||
}
|
|
||||||
else {
|
|
||||||
return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
|
||||||
DESKTOP_CREATEWINDOW |
|
|
||||||
DESKTOP_HOOKCONTROL |
|
|
||||||
GENERIC_WRITE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsDesks::closeDesktop(HDESK desk)
|
CMSWindowsDesks::closeDesktop(HDESK desk)
|
||||||
{
|
{
|
||||||
// on 95/98/me we don't need to close the desktop returned by
|
if (desk != NULL) {
|
||||||
// openInputDesktop().
|
|
||||||
if (desk != NULL && !m_is95Family) {
|
|
||||||
CloseDesktop(desk);
|
CloseDesktop(desk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1031,9 +964,6 @@ CMSWindowsDesks::getDesktopName(HDESK desk)
|
||||||
if (desk == NULL) {
|
if (desk == NULL) {
|
||||||
return CString();
|
return CString();
|
||||||
}
|
}
|
||||||
else if (m_is95Family) {
|
|
||||||
return "desktop";
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
DWORD size;
|
DWORD size;
|
||||||
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
||||||
|
|
|
@ -251,12 +251,6 @@ private:
|
||||||
// true if hooks are not to be installed (useful for debugging)
|
// true if hooks are not to be installed (useful for debugging)
|
||||||
bool m_noHooks;
|
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
|
// true if mouse has entered the screen
|
||||||
bool m_isOnScreen;
|
bool m_isOnScreen;
|
||||||
|
|
||||||
|
|
|
@ -579,7 +579,6 @@ static const CWin32Modifiers s_modifiers[] =
|
||||||
CMSWindowsKeyState::CMSWindowsKeyState(
|
CMSWindowsKeyState::CMSWindowsKeyState(
|
||||||
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events) :
|
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events) :
|
||||||
CKeyState(events),
|
CKeyState(events),
|
||||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
|
||||||
m_eventTarget(eventTarget),
|
m_eventTarget(eventTarget),
|
||||||
m_desks(desks),
|
m_desks(desks),
|
||||||
m_keyLayout(GetKeyboardLayout(0)),
|
m_keyLayout(GetKeyboardLayout(0)),
|
||||||
|
@ -596,7 +595,6 @@ CMSWindowsKeyState::CMSWindowsKeyState(
|
||||||
CMSWindowsKeyState::CMSWindowsKeyState(
|
CMSWindowsKeyState::CMSWindowsKeyState(
|
||||||
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events, CKeyMap& keyMap) :
|
CMSWindowsDesks* desks, void* eventTarget, IEventQueue* events, CKeyMap& keyMap) :
|
||||||
CKeyState(events, keyMap),
|
CKeyState(events, keyMap),
|
||||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
|
||||||
m_eventTarget(eventTarget),
|
m_eventTarget(eventTarget),
|
||||||
m_desks(desks),
|
m_desks(desks),
|
||||||
m_keyLayout(GetKeyboardLayout(0)),
|
m_keyLayout(GetKeyboardLayout(0)),
|
||||||
|
@ -761,10 +759,7 @@ CMSWindowsKeyState::mapKeyToVirtualKey(KeyID key) const
|
||||||
void
|
void
|
||||||
CMSWindowsKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState)
|
CMSWindowsKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState)
|
||||||
{
|
{
|
||||||
// handle win32 brokenness and forward to superclass
|
|
||||||
fixKeys();
|
|
||||||
CKeyState::onKey(button, down, newState);
|
CKeyState::onKey(button, down, newState);
|
||||||
fixKeys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -810,28 +805,22 @@ CMSWindowsKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
|
||||||
bool
|
bool
|
||||||
CMSWindowsKeyState::fakeCtrlAltDel()
|
CMSWindowsKeyState::fakeCtrlAltDel()
|
||||||
{
|
{
|
||||||
if (!m_is95Family) {
|
// to fake ctrl+alt+del on the NT family we broadcast a suitable
|
||||||
// to fake ctrl+alt+del on the NT family we broadcast a suitable
|
// hotkey to all windows on the winlogon desktop. however, the
|
||||||
// hotkey to all windows on the winlogon desktop. however, the
|
// current thread must be on that desktop to do the broadcast
|
||||||
// current thread must be on that desktop to do the broadcast
|
// and we can't switch just any thread because some own windows
|
||||||
// and we can't switch just any thread because some own windows
|
// or hooks. so start a new thread to do the real work.
|
||||||
// or hooks. so start a new thread to do the real work.
|
HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
|
||||||
HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
|
if ( hEvtSendSas ) {
|
||||||
if ( hEvtSendSas ) {
|
LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
|
||||||
LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
|
SetEvent( hEvtSendSas );
|
||||||
SetEvent( hEvtSendSas );
|
CloseHandle( hEvtSendSas );
|
||||||
CloseHandle( hEvtSendSas );
|
}
|
||||||
}
|
else {
|
||||||
else {
|
|
||||||
CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
|
CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
|
||||||
cad.wait();
|
cad.wait();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// simulate ctrl+alt+del
|
|
||||||
fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt,
|
|
||||||
virtualKeyToButton(VK_DELETE));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1006,11 +995,6 @@ CMSWindowsKeyState::getKeyMap(CKeyMap& keyMap)
|
||||||
|
|
||||||
case VK_LWIN:
|
case VK_LWIN:
|
||||||
case VK_RWIN:
|
case VK_RWIN:
|
||||||
// add extended key only for these on 95 family
|
|
||||||
if (m_is95Family) {
|
|
||||||
m_buttonToVK[i | 0x100u] = vk;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_RETURN:
|
case VK_RETURN:
|
||||||
|
@ -1351,77 +1335,6 @@ CMSWindowsKeyState::setWindowGroup(SInt32 group)
|
||||||
Sleep(100);
|
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
|
KeyID
|
||||||
CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
|
CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
|
||||||
{
|
{
|
||||||
|
@ -1436,21 +1349,12 @@ CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item,
|
||||||
KeyButton button, UINT virtualKey,
|
KeyButton button, UINT virtualKey,
|
||||||
PBYTE keyState, HKL hkl) const
|
PBYTE keyState, HKL hkl) const
|
||||||
{
|
{
|
||||||
int n;
|
WCHAR unicode[2];
|
||||||
KeyID id;
|
int n = m_ToUnicodeEx(
|
||||||
if (m_is95Family) {
|
virtualKey, button, keyState, unicode,
|
||||||
// XXX -- how do we get characters not in Latin-1?
|
sizeof(unicode) / sizeof(unicode[0]), 0, hkl);
|
||||||
WORD ascii;
|
KeyID id = static_cast<KeyID>(unicode[0]);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case -1:
|
case -1:
|
||||||
return CKeyMap::getDeadKey(id);
|
return CKeyMap::getDeadKey(id);
|
||||||
|
|
|
@ -167,9 +167,6 @@ private:
|
||||||
bool getGroups(GroupList&) const;
|
bool getGroups(GroupList&) const;
|
||||||
void setWindowGroup(SInt32 group);
|
void setWindowGroup(SInt32 group);
|
||||||
|
|
||||||
void fixKeys();
|
|
||||||
void handleFixKeys(const CEvent&, void*);
|
|
||||||
|
|
||||||
KeyID getIDForKey(CKeyMap::KeyItem& item,
|
KeyID getIDForKey(CKeyMap::KeyItem& item,
|
||||||
KeyButton button, UINT virtualKey,
|
KeyButton button, UINT virtualKey,
|
||||||
PBYTE keyState, HKL hkl) const;
|
PBYTE keyState, HKL hkl) const;
|
||||||
|
@ -187,7 +184,6 @@ private:
|
||||||
typedef std::map<HKL, SInt32> GroupMap;
|
typedef std::map<HKL, SInt32> GroupMap;
|
||||||
typedef std::map<KeyID, UINT> KeyToVKMap;
|
typedef std::map<KeyID, UINT> KeyToVKMap;
|
||||||
|
|
||||||
bool m_is95Family;
|
|
||||||
void* m_eventTarget;
|
void* m_eventTarget;
|
||||||
CMSWindowsDesks* m_desks;
|
CMSWindowsDesks* m_desks;
|
||||||
HKL m_keyLayout;
|
HKL m_keyLayout;
|
||||||
|
|
|
@ -97,7 +97,6 @@ CMSWindowsScreen::CMSWindowsScreen(
|
||||||
CPlatformScreen(events),
|
CPlatformScreen(events),
|
||||||
m_isPrimary(isPrimary),
|
m_isPrimary(isPrimary),
|
||||||
m_noHooks(noHooks),
|
m_noHooks(noHooks),
|
||||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
|
||||||
m_isOnScreen(m_isPrimary),
|
m_isOnScreen(m_isPrimary),
|
||||||
m_class(0),
|
m_class(0),
|
||||||
m_x(0), m_y(0),
|
m_x(0), m_y(0),
|
||||||
|
@ -1007,22 +1006,6 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
|
||||||
WPARAM wParam, LPARAM lParam, LRESULT* result)
|
WPARAM wParam, LPARAM lParam, LRESULT* result)
|
||||||
{
|
{
|
||||||
switch (msg) {
|
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:
|
case WM_DRAWCLIPBOARD:
|
||||||
// first pass on the message
|
// first pass on the message
|
||||||
if (m_nextClipboardWindow != NULL) {
|
if (m_nextClipboardWindow != NULL) {
|
||||||
|
@ -1183,37 +1166,6 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||||
KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
|
KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
|
||||||
button = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
|
button = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
|
||||||
if (key != kKeyNone) {
|
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
|
// do it
|
||||||
m_keyState->sendKeyEvent(getEventTarget(),
|
m_keyState->sendKeyEvent(getEventTarget(),
|
||||||
((lParam & 0x80000000u) == 0),
|
((lParam & 0x80000000u) == 0),
|
||||||
|
@ -1617,15 +1569,6 @@ CMSWindowsScreen::fixClipboardViewer()
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::enableSpecialKeys(bool enable) const
|
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
|
ButtonID
|
||||||
|
@ -1865,7 +1808,7 @@ CMSWindowsScreen::getDraggingFilename()
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::clearDraggingFilename()
|
CMSWindowsScreen::clearDraggingFilename()
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "clearing stored dragging file name"));
|
LOG((CLOG_DEBUG1 "clearing stored dragging file name"));
|
||||||
m_shellEx.clearDraggingFilename();
|
m_shellEx.clearDraggingFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -237,9 +237,6 @@ private:
|
||||||
// true if hooks are not to be installed (useful for debugging)
|
// true if hooks are not to be installed (useful for debugging)
|
||||||
bool m_noHooks;
|
bool m_noHooks;
|
||||||
|
|
||||||
// true if windows 95/98/me
|
|
||||||
bool m_is95Family;
|
|
||||||
|
|
||||||
// true if mouse has entered the screen
|
// true if mouse has entered the screen
|
||||||
bool m_isOnScreen;
|
bool m_isOnScreen;
|
||||||
|
|
||||||
|
|
|
@ -52,25 +52,6 @@ CMSWindowsScreenSaver::CMSWindowsScreenSaver() :
|
||||||
m_threadID(0),
|
m_threadID(0),
|
||||||
m_active(false)
|
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
|
// check if screen saver is enabled
|
||||||
SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0);
|
SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0);
|
||||||
}
|
}
|
||||||
|
@ -104,38 +85,19 @@ CMSWindowsScreenSaver::checkStarted(UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
m_wParam = wParam;
|
m_wParam = wParam;
|
||||||
m_lParam = lParam;
|
m_lParam = lParam;
|
||||||
|
|
||||||
// we handle the screen saver differently for the windows
|
// on the windows nt family we wait for the desktop to
|
||||||
// 95 and nt families.
|
// change until it's neither the Screen-Saver desktop
|
||||||
if (m_is95Family) {
|
// nor a desktop we can't open (the login desktop).
|
||||||
// on windows 95 we wait for the screen saver process
|
// since windows will send the request-to-start-screen-
|
||||||
// to terminate. get the process.
|
// saver message even when the screen saver is disabled
|
||||||
DWORD processID = findScreenSaver();
|
// we first check that the screen saver is indeed active
|
||||||
HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, processID);
|
// before watching for it to stop.
|
||||||
if (process == NULL) {
|
if (!isActive()) {
|
||||||
// didn't start
|
LOG((CLOG_DEBUG2 "can't open screen saver desktop"));
|
||||||
LOG((CLOG_DEBUG2 "can't open screen saver process"));
|
return false;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watchDesktop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,16 +155,15 @@ void
|
||||||
CMSWindowsScreenSaver::deactivate()
|
CMSWindowsScreenSaver::deactivate()
|
||||||
{
|
{
|
||||||
bool killed = false;
|
bool killed = false;
|
||||||
if (!m_is95Family) {
|
|
||||||
// NT runs screen saver in another desktop
|
// NT runs screen saver in another desktop
|
||||||
HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE,
|
HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE,
|
||||||
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
|
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
|
||||||
if (desktop != NULL) {
|
if (desktop != NULL) {
|
||||||
EnumDesktopWindows(desktop,
|
EnumDesktopWindows(desktop,
|
||||||
&CMSWindowsScreenSaver::killScreenSaverFunc,
|
&CMSWindowsScreenSaver::killScreenSaverFunc,
|
||||||
reinterpret_cast<LPARAM>(&killed));
|
reinterpret_cast<LPARAM>(&killed));
|
||||||
CloseDesktop(desktop);
|
CloseDesktop(desktop);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if above failed or wasn't tried, try the windows 95 way
|
// if above failed or wasn't tried, try the windows 95 way
|
||||||
|
@ -232,68 +193,9 @@ CMSWindowsScreenSaver::deactivate()
|
||||||
bool
|
bool
|
||||||
CMSWindowsScreenSaver::isActive() const
|
CMSWindowsScreenSaver::isActive() const
|
||||||
{
|
{
|
||||||
if (m_is95) {
|
BOOL running;
|
||||||
return (FindWindow("WindowsScreenSaverClass", NULL) != NULL);
|
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||||
}
|
return (running != FALSE);
|
||||||
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 CALLBACK
|
BOOL CALLBACK
|
||||||
|
@ -309,23 +211,6 @@ CMSWindowsScreenSaver::killScreenSaverFunc(HWND hwnd, LPARAM arg)
|
||||||
return TRUE;
|
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
|
void
|
||||||
CMSWindowsScreenSaver::watchDesktop()
|
CMSWindowsScreenSaver::watchDesktop()
|
||||||
{
|
{
|
||||||
|
@ -382,41 +267,10 @@ CMSWindowsScreenSaver::watchDesktopThread(void*)
|
||||||
// wait a bit
|
// wait a bit
|
||||||
ARCH->sleep(0.2);
|
ARCH->sleep(0.2);
|
||||||
|
|
||||||
if (m_isNT) {
|
BOOL running;
|
||||||
// get current desktop
|
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0);
|
||||||
HDESK desk = OpenInputDesktop(0, FALSE, GENERIC_READ);
|
if (running) {
|
||||||
if (desk == NULL) {
|
continue;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send screen saver deactivation message
|
// send screen saver deactivation message
|
||||||
|
@ -452,12 +306,11 @@ CMSWindowsScreenSaver::setSecure(bool secure, bool saveSecureAsInt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT;
|
|
||||||
if (saveSecureAsInt) {
|
if (saveSecureAsInt) {
|
||||||
CArchMiscWindows::setValue(hkey, isSecure, secure ? 1 : 0);
|
CArchMiscWindows::setValue(hkey, g_isSecureNT, secure ? 1 : 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CArchMiscWindows::setValue(hkey, isSecure, secure ? "1" : "0");
|
CArchMiscWindows::setValue(hkey, g_isSecureNT, secure ? "1" : "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
CArchMiscWindows::closeKey(hkey);
|
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
|
// get the value. the value may be an int or a string, depending
|
||||||
// on the version of windows.
|
// on the version of windows.
|
||||||
bool result;
|
bool result;
|
||||||
const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT;
|
switch (CArchMiscWindows::typeOfValue(hkey, g_isSecureNT)) {
|
||||||
switch (CArchMiscWindows::typeOfValue(hkey, isSecure)) {
|
|
||||||
default:
|
default:
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CArchMiscWindows::kUINT: {
|
case CArchMiscWindows::kUINT: {
|
||||||
DWORD value =
|
DWORD value =
|
||||||
CArchMiscWindows::readValueInt(hkey, isSecure);
|
CArchMiscWindows::readValueInt(hkey, g_isSecureNT);
|
||||||
*wasSecureFlagAnInt = true;
|
*wasSecureFlagAnInt = true;
|
||||||
result = (value != 0);
|
result = (value != 0);
|
||||||
break;
|
break;
|
||||||
|
@ -492,7 +344,7 @@ CMSWindowsScreenSaver::isSecure(bool* wasSecureFlagAnInt) const
|
||||||
|
|
||||||
case CArchMiscWindows::kSTRING: {
|
case CArchMiscWindows::kSTRING: {
|
||||||
std::string value =
|
std::string value =
|
||||||
CArchMiscWindows::readValueString(hkey, isSecure);
|
CArchMiscWindows::readValueString(hkey, g_isSecureNT);
|
||||||
*wasSecureFlagAnInt = false;
|
*wasSecureFlagAnInt = false;
|
||||||
result = (value != "0");
|
result = (value != "0");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -60,10 +60,8 @@ private:
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
static BOOL CALLBACK findScreenSaverFunc(HWND hwnd, LPARAM lParam);
|
|
||||||
static BOOL CALLBACK killScreenSaverFunc(HWND hwnd, LPARAM lParam);
|
static BOOL CALLBACK killScreenSaverFunc(HWND hwnd, LPARAM lParam);
|
||||||
|
|
||||||
DWORD findScreenSaver();
|
|
||||||
void watchDesktop();
|
void watchDesktop();
|
||||||
void watchProcess(HANDLE process);
|
void watchProcess(HANDLE process);
|
||||||
void unwatchProcess();
|
void unwatchProcess();
|
||||||
|
@ -74,9 +72,6 @@ private:
|
||||||
bool isSecure(bool* wasSecureAnInt) const;
|
bool isSecure(bool* wasSecureAnInt) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_is95Family;
|
|
||||||
bool m_is95;
|
|
||||||
bool m_isNT;
|
|
||||||
BOOL m_wasEnabled;
|
BOOL m_wasEnabled;
|
||||||
bool m_wasSecure;
|
bool m_wasSecure;
|
||||||
bool m_wasSecureAnInt;
|
bool m_wasSecureAnInt;
|
||||||
|
|
|
@ -17,20 +17,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "synergy/win32/AppUtilWindows.h"
|
#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/Screen.h"
|
||||||
#include "synergy/ArgsBase.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/IEventQueue.h"
|
||||||
#include "base/Event.h"
|
#include "base/Event.h"
|
||||||
#include "base/EventQueue.h"
|
#include "base/EventQueue.h"
|
||||||
|
#include "common/Version.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -156,6 +156,15 @@ CAppUtilWindows::beforeAppExit()
|
||||||
int
|
int
|
||||||
CAppUtilWindows::run(int argc, char** argv)
|
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
|
// record window instance for tray icon, etc
|
||||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue