diff --git a/checkin_notes b/checkin_notes index 1fc7e6a281..9de35e9dfb 100644 --- a/checkin_notes +++ b/checkin_notes @@ -6241,3 +6241,34 @@ David 6 Aug 2008 sched/ sched_config.C,h sched_result.C + +Rom 7 Aug 2008 + - CLIENT/MGR/TRAY: When installed on Vista and UAC is turned on + the user by default cannot create globally shared objects. This + becomes a problem when protected application mode is turned off + for keyboard and mouse detection. Basically all of the components + would start up and fail to create the shared memory segment + and report the error through stderr which most people don't look + at by default. + + The client is now the only component that is allowed to create the + shared memory segment, if creating the global segment fails it'll + create a local one instead. Both the tray and manager now just attach + to the existing segment, first trying the global one then the local + one. + + + client/ + main.C + clientgui/ + BOINCGUIApp.cpp, .h + clientlib/win/ + boinc_dll.cpp + IdleTracker.cpp + clienttray/ + tray_win.cpp, .h + win_build/ + boinc.sln + boinctray.vcproj + + \ No newline at end of file diff --git a/client/main.C b/client/main.C index 6ad1623802..62d6ae8788 100644 --- a/client/main.C +++ b/client/main.C @@ -33,6 +33,8 @@ static bool requested_suspend = false; static bool requested_resume = false; typedef BOOL (CALLBACK* ClientLibraryStartup)(); +typedef BOOL (CALLBACK* IdleTrackerStartup)(); +typedef void (CALLBACK* IdleTrackerShutdown)(); typedef void (CALLBACK* ClientLibraryShutdown)(); #ifndef _T #define _T(X) X @@ -410,9 +412,28 @@ int initialize() { #ifdef _WIN32 if(g_hClientLibraryDll) { ClientLibraryStartup fnClientLibraryStartup; + IdleTrackerStartup fnIdleTrackerStartup; + fnClientLibraryStartup = (ClientLibraryStartup)GetProcAddress(g_hClientLibraryDll, _T("ClientLibraryStartup")); if(fnClientLibraryStartup) { if(!fnClientLibraryStartup()) { + stprintf(event_message, + TEXT("BOINC Core Client Error Message\n" + "Failed to initialize the BOINC Client Library Interface.\n" + "BOINC will not be able to determine if the user is idle or not...\n" + "Load failed: %s\n"), windows_error_string(event_message, sizeof(event_message)) + ); + if (!gstate.executing_as_daemon) { + fprintf(stderr, event_message); + } else { + LogEventErrorMessage(event_message); + } + } + } + + fnIdleTrackerStartup = (IdleTrackerStartup)GetProcAddress(g_hClientLibraryDll, _T("IdleTrackerStartup")); + if(fnIdleTrackerStartup) { + if(!fnIdleTrackerStartup()) { stprintf(event_message, TEXT("BOINC Core Client Error Message\n" "Failed to initialize the BOINC Idle Detection Interface.\n" @@ -427,6 +448,7 @@ int initialize() { } } } + #endif return 0; } @@ -514,11 +536,19 @@ int finalize() { #ifdef _WIN32 if(g_hClientLibraryDll) { + IdleTrackerShutdown fnIdleTrackerShutdown; ClientLibraryShutdown fnClientLibraryShutdown; + + fnIdleTrackerShutdown = (IdleTrackerShutdown)GetProcAddress(g_hClientLibraryDll, _T("IdleTrackerShutdown")); + if(fnIdleTrackerShutdown) { + fnIdleTrackerShutdown(); + } + fnClientLibraryShutdown = (ClientLibraryShutdown)GetProcAddress(g_hClientLibraryDll, _T("ClientLibraryShutdown")); if(fnClientLibraryShutdown) { fnClientLibraryShutdown(); } + if(!FreeLibrary(g_hClientLibraryDll)) { stprintf(event_message, TEXT("BOINC Core Client Error Message\n" @@ -527,12 +557,14 @@ int finalize() { ), windows_error_string(event_message, sizeof(event_message)) ); + if (!gstate.executing_as_daemon) { fprintf(stderr, event_message); } else { LogEventErrorMessage(event_message); } } + g_hClientLibraryDll = NULL; } diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 1d2e5ee9f1..4b2f0a29ce 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -55,6 +55,8 @@ static bool s_bSkipExitConfirmation = false; #ifdef __WXMSW__ EXTERN_C BOOL ClientLibraryStartup(); +EXTERN_C BOOL IdleTrackerAttach(); +EXTERN_C void IdleTrackerDetach(); EXTERN_C void ClientLibraryShutdown(); EXTERN_C DWORD BOINCGetIdleTickCount(); #endif @@ -397,6 +399,7 @@ bool CBOINCGUIApp::OnInit() { // Startup the System Idle Detection code ClientLibraryStartup(); + IdleTrackerAttach(); #ifdef __WXMAC__ s_bSkipExitConfirmation = false; @@ -450,6 +453,7 @@ bool CBOINCGUIApp::OnInit() { int CBOINCGUIApp::OnExit() { // Shutdown the System Idle Detection code + IdleTrackerDetach(); ClientLibraryShutdown(); if (m_pDocument) { @@ -613,6 +617,22 @@ int CBOINCGUIApp::ClientLibraryStartup() { } +int CBOINCGUIApp::IdleTrackerAttach() { +#ifdef __WXMSW__ + ::IdleTrackerAttach(); +#endif + return 0; +} + + +int CBOINCGUIApp::IdleTrackerDetach() { +#ifdef __WXMSW__ + ::IdleTrackerDetach(); +#endif + return 0; +} + + int CBOINCGUIApp::ClientLibraryShutdown() { #ifdef __WXMSW__ ::ClientLibraryShutdown(); diff --git a/clientgui/BOINCGUIApp.h b/clientgui/BOINCGUIApp.h index 2949d94b01..0652be0dc6 100644 --- a/clientgui/BOINCGUIApp.h +++ b/clientgui/BOINCGUIApp.h @@ -55,6 +55,8 @@ protected: #endif int ClientLibraryStartup(); + int IdleTrackerAttach(); + int IdleTrackerDetach(); int ClientLibraryShutdown(); wxConfig* m_pConfig; diff --git a/clientlib/win/IdleTracker.cpp b/clientlib/win/IdleTracker.cpp index c86f46a36e..10720aabec 100644 --- a/clientlib/win/IdleTracker.cpp +++ b/clientlib/win/IdleTracker.cpp @@ -136,10 +136,11 @@ EXTERN_C __declspec(dllexport) DWORD BOINCGetIdleTickCount() return (dwCurrentTickCount - dwLastTickCount); } + /** * Initialize DLL: install kbd/mouse hooks. **/ -BOOL IdleTrackerStartup() +EXTERN_C __declspec(dllexport) BOOL IdleTrackerStartup() { BOOL bExists = FALSE; BOOL bResult = FALSE; @@ -206,6 +207,18 @@ BOOL IdleTrackerStartup() 4096, "Global\\BoincIdleTracker" ); + if( NULL == g_hMemoryMappedData ) + { + g_hMemoryMappedData = + CreateFileMapping( + INVALID_HANDLE_VALUE, + &sec_attr, + PAGE_READWRITE, + 0, + 4096, + "BoincIdleTracker" + ); + } if( NULL != g_hMemoryMappedData ) { @@ -249,10 +262,131 @@ BOOL IdleTrackerStartup() return bResult; } + +/** + * Initialize DLL: install kbd/mouse hooks. + **/ +EXTERN_C __declspec(dllexport) BOOL IdleTrackerAttach() +{ + BOOL bExists = FALSE; + BOOL bResult = FALSE; + SECURITY_ATTRIBUTES sec_attr; + SECURITY_DESCRIPTOR sd; + + + g_bIsWindows2000Compatible = IsWindows2000Compatible(); + g_bIsTerminalServicesEnabled = IsTerminalServicesEnabled(); + + + if ( !g_bIsWindows2000Compatible ) + { + if ( NULL == g_hHkKeyboard ) + { + g_hHkKeyboard = SetWindowsHookEx( + WH_KEYBOARD, + KeyboardTracker, + g_hModule, + 0 + ); + } + if ( NULL == g_hHkMouse ) + { + g_hHkMouse = SetWindowsHookEx( + WH_MOUSE, + MouseTracker, + g_hModule, + 0 + ); + } + + _ASSERT( g_hHkKeyboard ); + _ASSERT( g_hHkMouse ); + } + else + { + g_hUser32 = LoadLibrary("user32.dll"); + if (g_hUser32) + g_fnGetLastInputInfo = (GETLASTINPUTINFO)GetProcAddress(g_hUser32, "GetLastInputInfo"); + + + /* + * Create a security descriptor that will allow + * everyone full access. + */ + InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ); + SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE ); + + sec_attr.nLength = sizeof(sec_attr); + sec_attr.bInheritHandle = TRUE; + sec_attr.lpSecurityDescriptor = &sd; + + /* + * Create a filemap object that is global for everyone, + * including users logged in via terminal services. + */ + g_hMemoryMappedData = + OpenFileMapping( + FILE_MAP_READ | FILE_MAP_WRITE, + FALSE, + "Global\\BoincIdleTracker" + ); + if( NULL == g_hMemoryMappedData ) + { + g_hMemoryMappedData = + OpenFileMapping( + FILE_MAP_READ | FILE_MAP_WRITE, + FALSE, + "BoincIdleTracker" + ); + } + + if( NULL != g_hMemoryMappedData ) + { + if( ERROR_ALREADY_EXISTS == GetLastError() ) + bExists = TRUE; + + g_pSystemWideIdleData = (struct SystemWideIdleData*) + MapViewOfFile( + g_hMemoryMappedData, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 0 + ); + + _ASSERT( g_pSystemWideIdleData ); + } + + if( !bExists && g_pSystemWideIdleData ) + { + g_pSystemWideIdleData->dwLastTick = GetTickCount(); + } + } + + + if ( !g_bIsWindows2000Compatible ) + { + if ( !g_hHkKeyboard || !g_hHkMouse ) + bResult = FALSE; + else + bResult = TRUE; + } + else + { + if ( !g_hUser32 || !g_fnGetLastInputInfo || !g_hMemoryMappedData || !g_pSystemWideIdleData ) + bResult = FALSE; + else + bResult = TRUE; + } + + return bResult; +} + + /** * Terminate DLL: remove hooks. **/ -void IdleTrackerShutdown() +EXTERN_C __declspec(dllexport) void IdleTrackerDetach() { if ( !g_bIsWindows2000Compatible ) { @@ -283,4 +417,40 @@ void IdleTrackerShutdown() } } + +/** + * Terminate DLL: remove hooks. + **/ +EXTERN_C __declspec(dllexport) void IdleTrackerShutdown() +{ + if ( !g_bIsWindows2000Compatible ) + { + BOOL bResult; + if ( g_hHkKeyboard ) + { + bResult = UnhookWindowsHookEx( g_hHkKeyboard ); + _ASSERT( bResult ); + g_hHkKeyboard = NULL; + } + if ( g_hHkMouse ) + { + bResult = UnhookWindowsHookEx(g_hHkMouse); + _ASSERT( bResult ); + g_hHkMouse = NULL; + } + } + else + { + if( NULL != g_pSystemWideIdleData ) + { + UnmapViewOfFile(g_pSystemWideIdleData); + CloseHandle(g_hMemoryMappedData); + } + + if ( NULL != g_hUser32 ) + FreeLibrary(g_hUser32); + } +} + + const char *BOINC_RCSID_14d432d5b3 = "$Id$"; diff --git a/clientlib/win/boinc_dll.cpp b/clientlib/win/boinc_dll.cpp index 294fc130c1..89f7f6ab6d 100644 --- a/clientlib/win/boinc_dll.cpp +++ b/clientlib/win/boinc_dll.cpp @@ -44,14 +44,10 @@ BOOL APIENTRY DllMain( EXTERN_C __declspec(dllexport) BOOL ClientLibraryStartup() { - if (!IdleTrackerStartup()) - return FALSE; - return TRUE; } EXTERN_C __declspec(dllexport) void ClientLibraryShutdown() { - IdleTrackerShutdown(); } diff --git a/clienttray/tray_win.cpp b/clienttray/tray_win.cpp index 74b106421f..bfaf1defdf 100644 --- a/clienttray/tray_win.cpp +++ b/clienttray/tray_win.cpp @@ -22,9 +22,11 @@ #include "tray_win.h" - BOOL IdleTrackerStartup(); +EXTERN_C BOOL ClientLibraryStartup(); +EXTERN_C BOOL IdleTrackerAttach(); +EXTERN_C void IdleTrackerDetach(); +EXTERN_C void ClientLibraryShutdown(); EXTERN_C DWORD BOINCGetIdleTickCount(); - void IdleTrackerShutdown(); HMODULE g_hModule = NULL; static CBOINCTray* gspBOINCTray = NULL; @@ -41,6 +43,7 @@ CBOINCTray::CBOINCTray() { gspBOINCTray = this; m_hDataManagementThread = NULL; m_bClientLibraryInitialized = FALSE; + m_bIdleTrackerInitialized = FALSE; } @@ -48,9 +51,6 @@ CBOINCTray::CBOINCTray() { // INT CBOINCTray::Run( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { - // Initialize the BOINC client library to setup the idle tracking system. - m_bClientLibraryInitialized = IdleTrackerStartup(); - if (!hPrevInstance) { // Register an appropriate window class for the primary window WNDCLASS cls; @@ -87,7 +87,8 @@ INT CBOINCTray::Run( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi // Cleanup and shutdown the BOINC client library idle tracking system. - IdleTrackerShutdown(); + IdleTrackerDetach(); + ClientLibraryShutdown(); return msg.wParam; } @@ -132,12 +133,17 @@ BOOL CBOINCTray::DestroyDataManagementThread() { // DWORD WINAPI CBOINCTray::DataManagementProc() { while (true) { - if (!m_bClientLibraryInitialized) { + if (!m_bClientLibraryInitialized || !m_bIdleTrackerInitialized) { // On Vista systems, only elevated processes can create shared memory // area's across various user sessions. In this case we need to wait // for BOINC to create the shared memory area and then boinctray can // successfully attach to it. What a PITA. - m_bClientLibraryInitialized = IdleTrackerStartup(); + if (!m_bClientLibraryInitialized) { + m_bClientLibraryInitialized = ClientLibraryStartup(); + } + if (m_bClientLibraryInitialized && !m_bIdleTrackerInitialized) { + m_bIdleTrackerInitialized = IdleTrackerAttach(); + } } BOINCGetIdleTickCount(); diff --git a/clienttray/tray_win.h b/clienttray/tray_win.h index 7177ed4821..6cb07de53c 100644 --- a/clienttray/tray_win.h +++ b/clienttray/tray_win.h @@ -42,6 +42,7 @@ protected: HANDLE m_hDataManagementThread; BOOL m_bClientLibraryInitialized; + BOOL m_bIdleTrackerInitialized; }; #endif diff --git a/win_build/boinc.sln b/win_build/boinc.sln index 3b0277d224..715681bea8 100644 --- a/win_build/boinc.sln +++ b/win_build/boinc.sln @@ -2,8 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boinc", "boinc_cli_curl.vcproj", "{C04F0FCC-BB5D-4627-8656-6173B28BD69E}" ProjectSection(ProjectDependencies) = postProject - {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} = {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} {B06280CB-82A4-46DE-8956-602643078BDF} = {B06280CB-82A4-46DE-8956-602643078BDF} + {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} = {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boinc_dll", "boinc_dll.vcproj", "{B06280CB-82A4-46DE-8956-602643078BDF}" @@ -12,14 +12,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boinc_ss", "boinc_ss.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boinccmd", "boinccmd.vcproj", "{8F37E1F3-3A68-4A1D-9579-A1210BDD055E}" ProjectSection(ProjectDependencies) = postProject - {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} = {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} {C04F0FCC-BB5D-4627-8656-6173B28BD69E} = {C04F0FCC-BB5D-4627-8656-6173B28BD69E} + {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} = {E8F6BD7E-461A-4733-B7D8-37B09A099ED8} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boincmgr", "boincmgr_curl.vcproj", "{06113715-AC51-4E91-8B9D-C987CABE0920}" ProjectSection(ProjectDependencies) = postProject - {B06280CB-82A4-46DE-8956-602643078BDF} = {B06280CB-82A4-46DE-8956-602643078BDF} {C04F0FCC-BB5D-4627-8656-6173B28BD69E} = {C04F0FCC-BB5D-4627-8656-6173B28BD69E} + {B06280CB-82A4-46DE-8956-602643078BDF} = {B06280CB-82A4-46DE-8956-602643078BDF} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libboinc", "libboinc.vcproj", "{E8F6BD7E-461A-4733-B7D8-37B09A099ED8}" @@ -32,6 +32,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boincsim", "sim.vcproj", "{B950E31B-C075-4F6D-8A2B-25EAE9D46C93}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boinctray", "boinctray.vcproj", "{4A2C5963-6A8D-4DA1-A312-C3D749B2EA81}" + ProjectSection(ProjectDependencies) = postProject + {B06280CB-82A4-46DE-8956-602643078BDF} = {B06280CB-82A4-46DE-8956-602643078BDF} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/win_build/boinctray.vcproj b/win_build/boinctray.vcproj index eda40baecf..a129b4dcaf 100644 --- a/win_build/boinctray.vcproj +++ b/win_build/boinctray.vcproj @@ -676,18 +676,10 @@ Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > - - - - - - - -