Implemented basic display / sleep mode handling and added logging to taskbar.
This commit is contained in:
		
							parent
							
								
									49540af39d
								
							
						
					
					
						commit
						939bc7f79a
					
				
					 28 changed files with 436 additions and 174 deletions
				
			
		| 
						 | 
					@ -10,7 +10,7 @@ using System;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
					using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Configuration.Settings
 | 
					namespace SafeExamBrowser.Configuration
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public class BrowserSettings : IBrowserSettings
 | 
						public class BrowserSettings : IBrowserSettings
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
					using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Configuration.Settings
 | 
					namespace SafeExamBrowser.Configuration
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public class KeyboardSettings : IKeyboardSettings
 | 
						public class KeyboardSettings : IKeyboardSettings
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -8,12 +8,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
					using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Configuration.Settings
 | 
					namespace SafeExamBrowser.Configuration
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public class MouseSettings : IMouseSettings
 | 
						public class MouseSettings : IMouseSettings
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		public bool AllowMiddleButton => false;
 | 
							public bool AllowMiddleButton => false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public bool AllowRightButton => false;
 | 
							public bool AllowRightButton => true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -60,12 +60,10 @@
 | 
				
			||||||
    <Reference Include="System.Xml" />
 | 
					    <Reference Include="System.Xml" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <Compile Include="Bounds.cs" />
 | 
					    <Compile Include="BrowserSettings.cs" />
 | 
				
			||||||
    <Compile Include="Settings\BrowserSettings.cs" />
 | 
					    <Compile Include="KeyboardSettings.cs" />
 | 
				
			||||||
    <Compile Include="Settings\KeyboardSettings.cs" />
 | 
					    <Compile Include="MouseSettings.cs" />
 | 
				
			||||||
    <Compile Include="Settings\MouseSettings.cs" />
 | 
					    <Compile Include="Settings.cs" />
 | 
				
			||||||
    <Compile Include="Settings\SettingsImpl.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="WorkingArea.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
					    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,6 @@
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
using SafeExamBrowser.Configuration.Settings;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
					using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Configuration
 | 
					namespace SafeExamBrowser.Configuration
 | 
				
			||||||
| 
						 | 
					@ -17,11 +16,11 @@ namespace SafeExamBrowser.Configuration
 | 
				
			||||||
	/// <remarks>
 | 
						/// <remarks>
 | 
				
			||||||
	/// TODO: Replace with proper implementation once configuration aspects are clear...
 | 
						/// TODO: Replace with proper implementation once configuration aspects are clear...
 | 
				
			||||||
	/// </remarks>
 | 
						/// </remarks>
 | 
				
			||||||
	public class SettingsImpl : ISettings
 | 
						public class Settings : ISettings
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		private static readonly string LogFileDate = DateTime.Now.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
 | 
							private static readonly string LogFileDate = DateTime.Now.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public SettingsImpl()
 | 
							public Settings()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Browser = new BrowserSettings(this);
 | 
								Browser = new BrowserSettings(this);
 | 
				
			||||||
			Keyboard = new KeyboardSettings();
 | 
								Keyboard = new KeyboardSettings();
 | 
				
			||||||
| 
						 | 
					@ -1,62 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
					 | 
				
			||||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
					 | 
				
			||||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using System.Windows.Forms;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.WindowsApi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace SafeExamBrowser.Configuration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	public class WorkingArea : IWorkingArea
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		private ILogger logger;
 | 
					 | 
				
			||||||
		private INativeMethods nativeMethods;
 | 
					 | 
				
			||||||
		private IBounds originalWorkingArea;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public WorkingArea(ILogger logger, INativeMethods nativeMethods)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			this.logger = logger;
 | 
					 | 
				
			||||||
			this.nativeMethods = nativeMethods;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void InitializeFor(ITaskbar taskbar)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			originalWorkingArea = nativeMethods.GetWorkingArea();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			LogWorkingArea("Saved original working area", originalWorkingArea);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var area = new Bounds
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				Left = 0,
 | 
					 | 
				
			||||||
				Top = 0,
 | 
					 | 
				
			||||||
				Right = Screen.PrimaryScreen.Bounds.Width,
 | 
					 | 
				
			||||||
				Bottom = Screen.PrimaryScreen.Bounds.Height - taskbar.GetAbsoluteHeight()
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			LogWorkingArea("Trying to set new working area", area);
 | 
					 | 
				
			||||||
			nativeMethods.SetWorkingArea(area);
 | 
					 | 
				
			||||||
			LogWorkingArea("Working area is now set to", nativeMethods.GetWorkingArea());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void Reset()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (originalWorkingArea != null)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				nativeMethods.SetWorkingArea(originalWorkingArea);
 | 
					 | 
				
			||||||
				LogWorkingArea("Restored original working area", originalWorkingArea);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void LogWorkingArea(string message, IBounds area)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			logger.Info($"{message}: Left = {area.Left}, Top = {area.Top}, Right = {area.Right}, Bottom = {area.Bottom}.");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
					 | 
				
			||||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
					 | 
				
			||||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace SafeExamBrowser.Contracts.Configuration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	public interface IWorkingArea
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		/// <summary>
 | 
					 | 
				
			||||||
		/// Sets the Windows working area to accommodate to the taskbar's dimensions.
 | 
					 | 
				
			||||||
		/// </summary>
 | 
					 | 
				
			||||||
		void InitializeFor(ITaskbar taskbar);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/// <summary>
 | 
					 | 
				
			||||||
		/// Resets the Windows working area to its previous (initial) state.
 | 
					 | 
				
			||||||
		/// </summary>
 | 
					 | 
				
			||||||
		void Reset();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										41
									
								
								SafeExamBrowser.Contracts/Monitoring/IDisplayMonitor.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								SafeExamBrowser.Contracts/Monitoring/IDisplayMonitor.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SafeExamBrowser.Contracts.Monitoring
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public delegate void DisplayChangedEventHandler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public interface IDisplayMonitor
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Event fired when the primary display or its settings have changed.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							event DisplayChangedEventHandler DisplayChanged;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Sets the desktop working area to accommodate to the taskbar's height, removes the configured wallpaper (if possible) and
 | 
				
			||||||
 | 
							/// prevents the computer from entering sleep mode or turning its display(s) off.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							void InitializePrimaryDisplay(int taskbarHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Resets the desktop working area and wallpaper to their previous (initial) state.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							void ResetPrimaryDisplay();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Starts monitoring for display changes, i.e. display changes will trigger the <c>DisplaySettingsChanged</c> event.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							void StartMonitoringDisplayChanges();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Stops monitoring for display changes.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							void StopMonitoringDisplayChanges();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,6 @@
 | 
				
			||||||
    <Compile Include="Configuration\Settings\ISettings.cs" />
 | 
					    <Compile Include="Configuration\Settings\ISettings.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\IShutdownController.cs" />
 | 
					    <Compile Include="Behaviour\IShutdownController.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\IStartupController.cs" />
 | 
					    <Compile Include="Behaviour\IStartupController.cs" />
 | 
				
			||||||
    <Compile Include="Configuration\IWorkingArea.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="I18n\IText.cs" />
 | 
					    <Compile Include="I18n\IText.cs" />
 | 
				
			||||||
    <Compile Include="I18n\TextKey.cs" />
 | 
					    <Compile Include="I18n\TextKey.cs" />
 | 
				
			||||||
    <Compile Include="Logging\ILogContent.cs" />
 | 
					    <Compile Include="Logging\ILogContent.cs" />
 | 
				
			||||||
| 
						 | 
					@ -83,6 +82,7 @@
 | 
				
			||||||
    <Compile Include="Logging\ILogText.cs" />
 | 
					    <Compile Include="Logging\ILogText.cs" />
 | 
				
			||||||
    <Compile Include="Logging\IThreadInfo.cs" />
 | 
					    <Compile Include="Logging\IThreadInfo.cs" />
 | 
				
			||||||
    <Compile Include="Logging\LogLevel.cs" />
 | 
					    <Compile Include="Logging\LogLevel.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Monitoring\IDisplayMonitor.cs" />
 | 
				
			||||||
    <Compile Include="Monitoring\IKeyboardInterceptor.cs" />
 | 
					    <Compile Include="Monitoring\IKeyboardInterceptor.cs" />
 | 
				
			||||||
    <Compile Include="Monitoring\IMouseInterceptor.cs" />
 | 
					    <Compile Include="Monitoring\IMouseInterceptor.cs" />
 | 
				
			||||||
    <Compile Include="Monitoring\IProcessMonitor.cs" />
 | 
					    <Compile Include="Monitoring\IProcessMonitor.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,11 @@ namespace SafeExamBrowser.Contracts.WindowsApi
 | 
				
			||||||
		/// </exception>
 | 
							/// </exception>
 | 
				
			||||||
		void DeregisterSystemEvent(IntPtr handle);
 | 
							void DeregisterSystemEvent(IntPtr handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Prevents Windows from entering sleep mode and keeps all displays powered on.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							void DisableSleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Empties the clipboard.
 | 
							/// Empties the clipboard.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
| 
						 | 
					@ -72,8 +77,15 @@ namespace SafeExamBrowser.Contracts.WindowsApi
 | 
				
			||||||
		uint GetShellProcessId();
 | 
							uint GetShellProcessId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Retrieves the title of the specified window, or an empty string, if the
 | 
							/// Retrieves the path of the currently configured wallpaper image, or an empty string, if there is no wallpaper set.
 | 
				
			||||||
		/// given window does not have a title.
 | 
							/// </summary>
 | 
				
			||||||
 | 
							/// <exception cref="System.ComponentModel.Win32Exception">
 | 
				
			||||||
 | 
							/// If the wallpaper path could not be retrieved.
 | 
				
			||||||
 | 
							/// </exception>
 | 
				
			||||||
 | 
							string GetWallpaperPath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Retrieves the title of the specified window, or an empty string, if the given window does not have a title.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		string GetWindowTitle(IntPtr window);
 | 
							string GetWindowTitle(IntPtr window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,6 +137,14 @@ namespace SafeExamBrowser.Contracts.WindowsApi
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		IntPtr RegisterSystemCaptureStartEvent(Action<IntPtr> callback);
 | 
							IntPtr RegisterSystemCaptureStartEvent(Action<IntPtr> callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Removes the currently configured desktop wallpaper.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							/// <exception cref="System.ComponentModel.Win32Exception">
 | 
				
			||||||
 | 
							/// If the wallpaper could not be removed.
 | 
				
			||||||
 | 
							/// </exception>
 | 
				
			||||||
 | 
							void RemoveWallpaper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Restores the specified window to its original size and position.
 | 
							/// Restores the specified window to its original size and position.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
| 
						 | 
					@ -135,6 +155,14 @@ namespace SafeExamBrowser.Contracts.WindowsApi
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		void SendCloseMessageTo(IntPtr window);
 | 
							void SendCloseMessageTo(IntPtr window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Sets the wallpaper to the image located at the specified file path.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							/// <exception cref="System.ComponentModel.Win32Exception">
 | 
				
			||||||
 | 
							/// If the wallpaper could not be set.
 | 
				
			||||||
 | 
							/// </exception>
 | 
				
			||||||
 | 
							void SetWallpaper(string filePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Sets the working area of the primary screen according to the given dimensions.
 | 
							/// Sets the working area of the primary screen according to the given dimensions.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,6 @@ using System;
 | 
				
			||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
using Moq;
 | 
					using Moq;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Behaviour;
 | 
					using SafeExamBrowser.Contracts.Behaviour;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Monitoring;
 | 
					using SafeExamBrowser.Contracts.Monitoring;
 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					using SafeExamBrowser.Contracts.UserInterface;
 | 
				
			||||||
| 
						 | 
					@ -21,33 +20,52 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour
 | 
				
			||||||
	[TestClass]
 | 
						[TestClass]
 | 
				
			||||||
	public class RuntimeControllerTests
 | 
						public class RuntimeControllerTests
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							private Mock<IDisplayMonitor> displayMonitorMock;
 | 
				
			||||||
		private Mock<ILogger> loggerMock;
 | 
							private Mock<ILogger> loggerMock;
 | 
				
			||||||
		private Mock<IProcessMonitor> processMonitorMock;
 | 
							private Mock<IProcessMonitor> processMonitorMock;
 | 
				
			||||||
		private Mock<ITaskbar> taskbarMock;
 | 
							private Mock<ITaskbar> taskbarMock;
 | 
				
			||||||
		private Mock<IWindowMonitor> windowMonitorMock;
 | 
							private Mock<IWindowMonitor> windowMonitorMock;
 | 
				
			||||||
		private Mock<IWorkingArea> workingAreaMock;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private IRuntimeController sut;
 | 
							private IRuntimeController sut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestInitialize]
 | 
							[TestInitialize]
 | 
				
			||||||
		public void Initialize()
 | 
							public void Initialize()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								displayMonitorMock = new Mock<IDisplayMonitor>();
 | 
				
			||||||
			loggerMock = new Mock<ILogger>();
 | 
								loggerMock = new Mock<ILogger>();
 | 
				
			||||||
			processMonitorMock = new Mock<IProcessMonitor>();
 | 
								processMonitorMock = new Mock<IProcessMonitor>();
 | 
				
			||||||
			taskbarMock = new Mock<ITaskbar>();
 | 
								taskbarMock = new Mock<ITaskbar>();
 | 
				
			||||||
			windowMonitorMock= new Mock<IWindowMonitor>();
 | 
								windowMonitorMock= new Mock<IWindowMonitor>();
 | 
				
			||||||
			workingAreaMock = new Mock<IWorkingArea>();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut = new RuntimeController(
 | 
								sut = new RuntimeController(
 | 
				
			||||||
 | 
									displayMonitorMock.Object,
 | 
				
			||||||
				loggerMock.Object,
 | 
									loggerMock.Object,
 | 
				
			||||||
				processMonitorMock.Object,
 | 
									processMonitorMock.Object,
 | 
				
			||||||
				taskbarMock.Object,
 | 
									taskbarMock.Object,
 | 
				
			||||||
				windowMonitorMock.Object,
 | 
									windowMonitorMock.Object);
 | 
				
			||||||
				workingAreaMock.Object);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sut.Start();
 | 
								sut.Start();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[TestMethod]
 | 
				
			||||||
 | 
							public void MustHandleDisplayChangeCorrectly()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var order = 0;
 | 
				
			||||||
 | 
								var workingArea = 0;
 | 
				
			||||||
 | 
								var taskbar = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
 | 
				
			||||||
 | 
								taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								displayMonitorMock.Raise(d => d.DisplayChanged += null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once);
 | 
				
			||||||
 | 
								taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.IsTrue(workingArea == 1);
 | 
				
			||||||
 | 
								Assert.IsTrue(taskbar == 2);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[TestMethod]
 | 
							[TestMethod]
 | 
				
			||||||
		public void MustHandleExplorerStartCorrectly()
 | 
							public void MustHandleExplorerStartCorrectly()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -57,13 +75,13 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour
 | 
				
			||||||
			var taskbar = 0;
 | 
								var taskbar = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			processMonitorMock.Setup(p => p.CloseExplorerShell()).Callback(() => processManager = ++order);
 | 
								processMonitorMock.Setup(p => p.CloseExplorerShell()).Callback(() => processManager = ++order);
 | 
				
			||||||
			workingAreaMock.Setup(w => w.InitializeFor(taskbarMock.Object)).Callback(() => workingArea = ++order);
 | 
								displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
 | 
				
			||||||
			taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
 | 
								taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			processMonitorMock.Raise(p => p.ExplorerStarted += null);
 | 
								processMonitorMock.Raise(p => p.ExplorerStarted += null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			processMonitorMock.Verify(p => p.CloseExplorerShell(), Times.Once);
 | 
								processMonitorMock.Verify(p => p.CloseExplorerShell(), Times.Once);
 | 
				
			||||||
			workingAreaMock.Verify(w => w.InitializeFor(taskbarMock.Object), Times.Once);
 | 
								displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once);
 | 
				
			||||||
			taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
 | 
								taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Assert.IsTrue(processManager == 1);
 | 
								Assert.IsTrue(processManager == 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,26 +7,26 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using SafeExamBrowser.Contracts.Behaviour;
 | 
					using SafeExamBrowser.Contracts.Behaviour;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.I18n;
 | 
					using SafeExamBrowser.Contracts.I18n;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Contracts.Monitoring;
 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					using SafeExamBrowser.Contracts.UserInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
					namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public class WorkingAreaOperation : IOperation
 | 
						public class DisplayMonitorOperation : IOperation
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							private IDisplayMonitor displayMonitor;
 | 
				
			||||||
		private ILogger logger;
 | 
							private ILogger logger;
 | 
				
			||||||
		private ITaskbar taskbar;
 | 
							private ITaskbar taskbar;
 | 
				
			||||||
		private IWorkingArea workingArea;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public ISplashScreen SplashScreen { private get; set; }
 | 
							public ISplashScreen SplashScreen { private get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public WorkingAreaOperation(ILogger logger, ITaskbar taskbar, IWorkingArea workingArea)
 | 
							public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, ITaskbar taskbar)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								this.displayMonitor = displayMonitor;
 | 
				
			||||||
			this.logger = logger;
 | 
								this.logger = logger;
 | 
				
			||||||
			this.taskbar = taskbar;
 | 
								this.taskbar = taskbar;
 | 
				
			||||||
			this.workingArea = workingArea;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Perform()
 | 
							public void Perform()
 | 
				
			||||||
| 
						 | 
					@ -34,10 +34,8 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
				
			||||||
			logger.Info("Initializing working area...");
 | 
								logger.Info("Initializing working area...");
 | 
				
			||||||
			SplashScreen.UpdateText(TextKey.SplashScreen_InitializeWorkingArea);
 | 
								SplashScreen.UpdateText(TextKey.SplashScreen_InitializeWorkingArea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO
 | 
								displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
 | 
				
			||||||
			// - Emptying clipboard
 | 
								displayMonitor.StartMonitoringDisplayChanges();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			workingArea.InitializeFor(taskbar);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Revert()
 | 
							public void Revert()
 | 
				
			||||||
| 
						 | 
					@ -45,10 +43,8 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
				
			||||||
			logger.Info("Restoring working area...");
 | 
								logger.Info("Restoring working area...");
 | 
				
			||||||
			SplashScreen.UpdateText(TextKey.SplashScreen_RestoreWorkingArea);
 | 
								SplashScreen.UpdateText(TextKey.SplashScreen_RestoreWorkingArea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// TODO
 | 
								displayMonitor.StopMonitoringDisplayChanges();
 | 
				
			||||||
			// - Emptying clipboard
 | 
								displayMonitor.ResetPrimaryDisplay();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			workingArea.Reset();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Behaviour;
 | 
					using SafeExamBrowser.Contracts.Behaviour;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Configuration;
 | 
					 | 
				
			||||||
using SafeExamBrowser.Contracts.Logging;
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
using SafeExamBrowser.Contracts.Monitoring;
 | 
					using SafeExamBrowser.Contracts.Monitoring;
 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					using SafeExamBrowser.Contracts.UserInterface;
 | 
				
			||||||
| 
						 | 
					@ -17,28 +16,29 @@ namespace SafeExamBrowser.Core.Behaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public class RuntimeController : IRuntimeController
 | 
						public class RuntimeController : IRuntimeController
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							private IDisplayMonitor displayMonitor;
 | 
				
			||||||
		private ILogger logger;
 | 
							private ILogger logger;
 | 
				
			||||||
		private IProcessMonitor processMonitor;
 | 
							private IProcessMonitor processMonitor;
 | 
				
			||||||
		private ITaskbar taskbar;
 | 
							private ITaskbar taskbar;
 | 
				
			||||||
		private IWindowMonitor windowMonitor;
 | 
							private IWindowMonitor windowMonitor;
 | 
				
			||||||
		private IWorkingArea workingArea;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public RuntimeController(
 | 
							public RuntimeController(
 | 
				
			||||||
 | 
								IDisplayMonitor displayMonitor,
 | 
				
			||||||
			ILogger logger,
 | 
								ILogger logger,
 | 
				
			||||||
			IProcessMonitor processMonitor,
 | 
								IProcessMonitor processMonitor,
 | 
				
			||||||
			ITaskbar taskbar,
 | 
								ITaskbar taskbar,
 | 
				
			||||||
			IWindowMonitor windowMonitor,
 | 
								IWindowMonitor windowMonitor)
 | 
				
			||||||
			IWorkingArea workingArea)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								this.displayMonitor = displayMonitor;
 | 
				
			||||||
			this.logger = logger;
 | 
								this.logger = logger;
 | 
				
			||||||
			this.processMonitor = processMonitor;
 | 
								this.processMonitor = processMonitor;
 | 
				
			||||||
			this.taskbar = taskbar;
 | 
								this.taskbar = taskbar;
 | 
				
			||||||
			this.windowMonitor = windowMonitor;
 | 
								this.windowMonitor = windowMonitor;
 | 
				
			||||||
			this.workingArea = workingArea;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void Start()
 | 
							public void Start()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged;
 | 
				
			||||||
			processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
 | 
								processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted;
 | 
				
			||||||
			windowMonitor.WindowChanged += WindowMonitor_WindowChanged;
 | 
								windowMonitor.WindowChanged += WindowMonitor_WindowChanged;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -49,12 +49,21 @@ namespace SafeExamBrowser.Core.Behaviour
 | 
				
			||||||
			windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
 | 
								windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void DisplayMonitor_DisplaySettingsChanged()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								logger.Info("Reinitializing working area...");
 | 
				
			||||||
 | 
								displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
 | 
				
			||||||
 | 
								logger.Info("Reinitializing taskbar bounds...");
 | 
				
			||||||
 | 
								taskbar.InitializeBounds();
 | 
				
			||||||
 | 
								logger.Info("Desktop successfully restored.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private void ProcessMonitor_ExplorerStarted()
 | 
							private void ProcessMonitor_ExplorerStarted()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			logger.Info("Trying to shut down explorer...");
 | 
								logger.Info("Trying to shut down explorer...");
 | 
				
			||||||
			processMonitor.CloseExplorerShell();
 | 
								processMonitor.CloseExplorerShell();
 | 
				
			||||||
			logger.Info("Reinitializing working area...");
 | 
								logger.Info("Reinitializing working area...");
 | 
				
			||||||
			workingArea.InitializeFor(taskbar);
 | 
								displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
 | 
				
			||||||
			logger.Info("Reinitializing taskbar bounds...");
 | 
								logger.Info("Reinitializing taskbar bounds...");
 | 
				
			||||||
			taskbar.InitializeBounds();
 | 
								taskbar.InitializeBounds();
 | 
				
			||||||
			logger.Info("Desktop successfully restored.");
 | 
								logger.Info("Desktop successfully restored.");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@
 | 
				
			||||||
    <Compile Include="Behaviour\Operations\ProcessMonitorOperation.cs" />
 | 
					    <Compile Include="Behaviour\Operations\ProcessMonitorOperation.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\Operations\TaskbarOperation.cs" />
 | 
					    <Compile Include="Behaviour\Operations\TaskbarOperation.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\Operations\WindowMonitorOperation.cs" />
 | 
					    <Compile Include="Behaviour\Operations\WindowMonitorOperation.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\Operations\WorkingAreaOperation.cs" />
 | 
					    <Compile Include="Behaviour\Operations\DisplayMonitorOperation.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\ShutdownController.cs" />
 | 
					    <Compile Include="Behaviour\ShutdownController.cs" />
 | 
				
			||||||
    <Compile Include="Behaviour\StartupController.cs" />
 | 
					    <Compile Include="Behaviour\StartupController.cs" />
 | 
				
			||||||
    <Compile Include="Logging\DefaultLogFormatter.cs" />
 | 
					    <Compile Include="Logging\DefaultLogFormatter.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using SafeExamBrowser.Contracts.WindowsApi;
 | 
					using SafeExamBrowser.Contracts.WindowsApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.Configuration
 | 
					namespace SafeExamBrowser.Monitoring.Display
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	internal class Bounds : IBounds
 | 
						internal class Bounds : IBounds
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
							
								
								
									
										139
									
								
								SafeExamBrowser.Monitoring/Display/DisplayMonitor.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								SafeExamBrowser.Monitoring/Display/DisplayMonitor.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,139 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Windows.Forms;
 | 
				
			||||||
 | 
					using Microsoft.Win32;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Contracts.Monitoring;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Contracts.WindowsApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SafeExamBrowser.Monitoring.Display
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DisplayMonitor : IDisplayMonitor
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							private IBounds originalWorkingArea;
 | 
				
			||||||
 | 
							private ILogger logger;
 | 
				
			||||||
 | 
							private INativeMethods nativeMethods;
 | 
				
			||||||
 | 
							private string wallpaper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public event DisplayChangedEventHandler DisplayChanged;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public DisplayMonitor(ILogger logger, INativeMethods nativeMethods)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								this.logger = logger;
 | 
				
			||||||
 | 
								this.nativeMethods = nativeMethods;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void InitializePrimaryDisplay(int taskbarHeight)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								InitializeWorkingArea(taskbarHeight);
 | 
				
			||||||
 | 
								InitializeWallpaper();
 | 
				
			||||||
 | 
								PreventSleepMode();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void ResetPrimaryDisplay()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ResetWorkingArea();
 | 
				
			||||||
 | 
								ResetWallpaper();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void StartMonitoringDisplayChanges()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
 | 
				
			||||||
 | 
								logger.Info("Started monitoring display changes.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void StopMonitoringDisplayChanges()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
 | 
				
			||||||
 | 
								logger.Info("Stopped monitoring display changes.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								logger.Info("Display change detected!");
 | 
				
			||||||
 | 
								DisplayChanged?.Invoke();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void InitializeWorkingArea(int taskbarHeight)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var identifier = GetIdentifierForPrimaryDisplay();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								originalWorkingArea = nativeMethods.GetWorkingArea();
 | 
				
			||||||
 | 
								LogWorkingArea($"Saved original working area for {identifier}", originalWorkingArea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var area = new Bounds
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Left = 0,
 | 
				
			||||||
 | 
									Top = 0,
 | 
				
			||||||
 | 
									Right = Screen.PrimaryScreen.Bounds.Width,
 | 
				
			||||||
 | 
									Bottom = Screen.PrimaryScreen.Bounds.Height - taskbarHeight
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								LogWorkingArea($"Trying to set new working area for {identifier}", area);
 | 
				
			||||||
 | 
								nativeMethods.SetWorkingArea(area);
 | 
				
			||||||
 | 
								LogWorkingArea($"Working area of {identifier} is now set to", nativeMethods.GetWorkingArea());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void InitializeWallpaper()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var path = nativeMethods.GetWallpaperPath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!String.IsNullOrEmpty(path))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									wallpaper = path;
 | 
				
			||||||
 | 
									logger.Info($"Saved wallpaper image: {wallpaper}.");
 | 
				
			||||||
 | 
									nativeMethods.RemoveWallpaper();
 | 
				
			||||||
 | 
									logger.Info("Removed current wallpaper.");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void PreventSleepMode()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								nativeMethods.DisableSleep();
 | 
				
			||||||
 | 
								logger.Info("Disabled sleep mode and display timeout.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void ResetWorkingArea()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var identifier = GetIdentifierForPrimaryDisplay();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (originalWorkingArea != null)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									nativeMethods.SetWorkingArea(originalWorkingArea);
 | 
				
			||||||
 | 
									LogWorkingArea($"Restored original working area for {identifier}", originalWorkingArea);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									logger.Warn($"Could not restore original working area for {identifier}!");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void ResetWallpaper()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!String.IsNullOrEmpty(wallpaper))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									nativeMethods.SetWallpaper(wallpaper);
 | 
				
			||||||
 | 
									logger.Info($"Restored wallpaper image: {wallpaper}.");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private string GetIdentifierForPrimaryDisplay()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var display = Screen.PrimaryScreen.DeviceName?.Replace(@"\\.\", string.Empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return $"{display} ({Screen.PrimaryScreen.Bounds.Width}x{Screen.PrimaryScreen.Bounds.Height})";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void LogWorkingArea(string message, IBounds area)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								logger.Info($"{message}: Left = {area.Left}, Top = {area.Top}, Right = {area.Right}, Bottom = {area.Bottom}.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,9 @@
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <Reference Include="System" />
 | 
					    <Reference Include="System" />
 | 
				
			||||||
    <Reference Include="System.Core" />
 | 
					    <Reference Include="System.Core" />
 | 
				
			||||||
 | 
					    <Reference Include="System.Drawing" />
 | 
				
			||||||
    <Reference Include="System.Management" />
 | 
					    <Reference Include="System.Management" />
 | 
				
			||||||
 | 
					    <Reference Include="System.Windows.Forms" />
 | 
				
			||||||
    <Reference Include="System.Xml.Linq" />
 | 
					    <Reference Include="System.Xml.Linq" />
 | 
				
			||||||
    <Reference Include="System.Data.DataSetExtensions" />
 | 
					    <Reference Include="System.Data.DataSetExtensions" />
 | 
				
			||||||
    <Reference Include="Microsoft.CSharp" />
 | 
					    <Reference Include="Microsoft.CSharp" />
 | 
				
			||||||
| 
						 | 
					@ -60,10 +62,13 @@
 | 
				
			||||||
    <Reference Include="WindowsBase" />
 | 
					    <Reference Include="WindowsBase" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Compile Include="Display\Bounds.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Display\DisplayMonitor.cs" />
 | 
				
			||||||
    <Compile Include="Keyboard\KeyboardInterceptor.cs" />
 | 
					    <Compile Include="Keyboard\KeyboardInterceptor.cs" />
 | 
				
			||||||
    <Compile Include="Mouse\MouseInterceptor.cs" />
 | 
					    <Compile Include="Mouse\MouseInterceptor.cs" />
 | 
				
			||||||
    <Compile Include="Processes\ProcessMonitor.cs" />
 | 
					    <Compile Include="Processes\ProcessMonitor.cs" />
 | 
				
			||||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
					    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Windows\Window.cs" />
 | 
				
			||||||
    <Compile Include="Windows\WindowMonitor.cs" />
 | 
					    <Compile Include="Windows\WindowMonitor.cs" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								SafeExamBrowser.Monitoring/Windows/Window.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								SafeExamBrowser.Monitoring/Windows/Window.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SafeExamBrowser.Monitoring.Windows
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						internal struct Window
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							internal IntPtr Handle { get; set; }
 | 
				
			||||||
 | 
							internal string Title { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -117,11 +117,5 @@ namespace SafeExamBrowser.Monitoring.Windows
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			WindowChanged?.Invoke(window);
 | 
								WindowChanged?.Invoke(window);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		private struct Window
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			internal IntPtr Handle { get; set; }
 | 
					 | 
				
			||||||
			internal string Title { get; set; }
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,14 +10,19 @@ using System.Windows;
 | 
				
			||||||
using System.Windows.Input;
 | 
					using System.Windows.Input;
 | 
				
			||||||
using System.Windows.Interop;
 | 
					using System.Windows.Interop;
 | 
				
			||||||
using System.Windows.Media;
 | 
					using System.Windows.Media;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Contracts.Logging;
 | 
				
			||||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
					using SafeExamBrowser.Contracts.UserInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.UserInterface
 | 
					namespace SafeExamBrowser.UserInterface
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public partial class Taskbar : Window, ITaskbar
 | 
						public partial class Taskbar : Window, ITaskbar
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		public Taskbar()
 | 
							private ILogger logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public Taskbar(ILogger logger)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								this.logger = logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			InitializeComponent();
 | 
								InitializeComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Loaded += (o, args) => InitializeBounds();
 | 
								Loaded += (o, args) => InitializeBounds();
 | 
				
			||||||
| 
						 | 
					@ -41,28 +46,13 @@ namespace SafeExamBrowser.UserInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int GetAbsoluteHeight()
 | 
							public int GetAbsoluteHeight()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// WPF works with device-independent pixels. The following code is required
 | 
					 | 
				
			||||||
			// to get the real height of the taskbar (in absolute, device-specific pixels).
 | 
					 | 
				
			||||||
			// Source: https://stackoverflow.com/questions/3286175/how-do-i-convert-a-wpf-size-to-physical-pixels
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return Dispatcher.Invoke(() =>
 | 
								return Dispatcher.Invoke(() =>
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Matrix transformToDevice;
 | 
									var height = (int) TransformToPhysical(Width, Height).Y;
 | 
				
			||||||
				var source = PresentationSource.FromVisual(this);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (source != null)
 | 
									logger.Info($"Calculated absolute taskbar height is {height}px.");
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					transformToDevice = source.CompositionTarget.TransformToDevice;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					using (var newSource = new HwndSource(new HwndSourceParameters()))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						transformToDevice = newSource.CompositionTarget.TransformToDevice;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				return (int)transformToDevice.Transform((Vector)new Size(Width, Height)).Y;
 | 
									return height;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +63,11 @@ namespace SafeExamBrowser.UserInterface
 | 
				
			||||||
				Width = SystemParameters.WorkArea.Right;
 | 
									Width = SystemParameters.WorkArea.Right;
 | 
				
			||||||
				Left = SystemParameters.WorkArea.Right - Width;
 | 
									Left = SystemParameters.WorkArea.Right - Width;
 | 
				
			||||||
				Top = SystemParameters.WorkArea.Bottom;
 | 
									Top = SystemParameters.WorkArea.Bottom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var position = TransformToPhysical(Left, Top);
 | 
				
			||||||
 | 
									var size = TransformToPhysical(Width, Height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									logger.Info($"Set taskbar bounds to {Width}x{Height} at ({Left}/{Top}), in physical pixels: {size.X}x{size.Y} at ({position.X}/{position.Y}).");
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,5 +101,29 @@ namespace SafeExamBrowser.UserInterface
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private Vector TransformToPhysical(double x, double y)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// WPF works with device-independent pixels. The following code is required
 | 
				
			||||||
 | 
								// to transform those values to their absolute, device-specific pixel value.
 | 
				
			||||||
 | 
								// Source: https://stackoverflow.com/questions/3286175/how-do-i-convert-a-wpf-size-to-physical-pixels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Matrix transformToDevice;
 | 
				
			||||||
 | 
								var source = PresentationSource.FromVisual(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (source != null)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									transformToDevice = source.CompositionTarget.TransformToDevice;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									using (var newSource = new HwndSource(new HwndSourceParameters()))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										transformToDevice = newSource.CompositionTarget.TransformToDevice;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return transformToDevice.Transform(new Vector(x, y));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,12 +14,11 @@ namespace SafeExamBrowser.WindowsApi.Constants
 | 
				
			||||||
	internal enum SPI : uint
 | 
						internal enum SPI : uint
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Sets the size of the work area. The work area is the portion of the screen not obscured by the system taskbar
 | 
							/// Retrieves the full path of the bitmap file for the desktop wallpaper. The pvParam parameter must point to a buffer
 | 
				
			||||||
		/// or by application desktop toolbars. The pvParam parameter is a pointer to a RECT structure that specifies the
 | 
							/// that receives a null-terminated path string. Set the uiParam parameter to the size, in characters, of the pvParam buffer.
 | 
				
			||||||
		/// new work area rectangle, expressed in virtual screen coordinates. In a system with multiple display monitors,
 | 
							/// The returned string will not exceed MAX_PATH characters. If there is no desktop wallpaper, the returned string is empty.
 | 
				
			||||||
		/// the function sets the work area of the monitor that contains the specified rectangle.
 | 
					 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		SETWORKAREA = 0x002F,
 | 
							GETDESKWALLPAPER = 0x73,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen
 | 
							/// Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen
 | 
				
			||||||
| 
						 | 
					@ -27,6 +26,21 @@ namespace SafeExamBrowser.WindowsApi.Constants
 | 
				
			||||||
		/// RECT structure that receives the coordinates of the work area, expressed in virtual screen coordinates. To get
 | 
							/// RECT structure that receives the coordinates of the work area, expressed in virtual screen coordinates. To get
 | 
				
			||||||
		/// the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function.
 | 
							/// the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function.
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		GETWORKAREA = 0x0030,
 | 
							GETWORKAREA = 0x30,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Sets the desktop wallpaper. The value of the pvParam parameter determines the new wallpaper. To specify a wallpaper bitmap,
 | 
				
			||||||
 | 
							/// set pvParam to point to a null-terminated string containing the name of a bitmap file. Setting pvParam to "" removes the
 | 
				
			||||||
 | 
							/// wallpaper. Setting pvParam to SETWALLPAPER_DEFAULT or null reverts to the default wallpaper.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							SETDESKWALLPAPER = 0x14,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// Sets the size of the work area. The work area is the portion of the screen not obscured by the system taskbar
 | 
				
			||||||
 | 
							/// or by application desktop toolbars. The pvParam parameter is a pointer to a RECT structure that specifies the
 | 
				
			||||||
 | 
							/// new work area rectangle, expressed in virtual screen coordinates. In a system with multiple display monitors,
 | 
				
			||||||
 | 
							/// the function sets the work area of the monitor that contains the specified rectangle.
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							SETWORKAREA = 0x2F,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					using SafeExamBrowser.WindowsApi.Types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.WindowsApi
 | 
					namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -16,7 +17,10 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
	/// </summary>
 | 
						/// </summary>
 | 
				
			||||||
	internal class Kernel32
 | 
						internal class Kernel32
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
 | 
							[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 | 
				
			||||||
		public static extern IntPtr GetModuleHandle(string lpModuleName);
 | 
							internal static extern IntPtr GetModuleHandle(string lpModuleName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[DllImport("kernel32.dll", SetLastError = true)]
 | 
				
			||||||
 | 
							internal static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,6 +94,11 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
			EventDelegates.TryRemove(handle, out EventProc d);
 | 
								EventDelegates.TryRemove(handle, out EventProc d);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void DisableSleep()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Kernel32.SetThreadExecutionState(EXECUTION_STATE.CONTINUOUS | EXECUTION_STATE.DISPLAY_REQUIRED | EXECUTION_STATE.SYSTEM_REQUIRED);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void EmptyClipboard()
 | 
							public void EmptyClipboard()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var success = true;
 | 
								var success = true;
 | 
				
			||||||
| 
						 | 
					@ -149,6 +154,22 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
			return processId;
 | 
								return processId;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public string GetWallpaperPath()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								const int MAX_PATH = 260;
 | 
				
			||||||
 | 
								var buffer = new String('\0', MAX_PATH);
 | 
				
			||||||
 | 
								var success = User32.SystemParametersInfo(SPI.GETDESKWALLPAPER, buffer.Length, buffer, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!success)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									throw new Win32Exception(Marshal.GetLastWin32Error());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var path = buffer.Substring(0, buffer.IndexOf('\0'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return path;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public string GetWindowTitle(IntPtr window)
 | 
							public string GetWindowTitle(IntPtr window)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var length = User32.GetWindowTextLength(window);
 | 
								var length = User32.GetWindowTextLength(window);
 | 
				
			||||||
| 
						 | 
					@ -256,6 +277,11 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
			return handle;
 | 
								return handle;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void RemoveWallpaper()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SetWallpaper(string.Empty);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void RestoreWindow(IntPtr window)
 | 
							public void RestoreWindow(IntPtr window)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			User32.ShowWindow(window, (int)ShowWindowCommand.Restore);
 | 
								User32.ShowWindow(window, (int)ShowWindowCommand.Restore);
 | 
				
			||||||
| 
						 | 
					@ -266,6 +292,16 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
			User32.SendMessage(window, Constant.WM_SYSCOMMAND, (IntPtr) SystemCommand.CLOSE, IntPtr.Zero);
 | 
								User32.SendMessage(window, Constant.WM_SYSCOMMAND, (IntPtr) SystemCommand.CLOSE, IntPtr.Zero);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public void SetWallpaper(string filePath)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var success = User32.SystemParametersInfo(SPI.SETDESKWALLPAPER, 0, filePath, SPIF.UPDATEANDCHANGE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!success)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									throw new Win32Exception(Marshal.GetLastWin32Error());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void SetWorkingArea(IBounds bounds)
 | 
							public void SetWorkingArea(IBounds bounds)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			var workingArea = new RECT { Left = bounds.Left, Top = bounds.Top, Right = bounds.Right, Bottom = bounds.Bottom };
 | 
								var workingArea = new RECT { Left = bounds.Left, Top = bounds.Top, Right = bounds.Right, Bottom = bounds.Bottom };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,7 @@
 | 
				
			||||||
    <Compile Include="Constants\HookType.cs" />
 | 
					    <Compile Include="Constants\HookType.cs" />
 | 
				
			||||||
    <Compile Include="Monitoring\MouseHook.cs" />
 | 
					    <Compile Include="Monitoring\MouseHook.cs" />
 | 
				
			||||||
    <Compile Include="Types\Bounds.cs" />
 | 
					    <Compile Include="Types\Bounds.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Types\EXECUTION_STATE.cs" />
 | 
				
			||||||
    <Compile Include="Types\KBDLLHOOKSTRUCT.cs" />
 | 
					    <Compile Include="Types\KBDLLHOOKSTRUCT.cs" />
 | 
				
			||||||
    <Compile Include="Types\KBDLLHOOKSTRUCTFlags.cs" />
 | 
					    <Compile Include="Types\KBDLLHOOKSTRUCTFlags.cs" />
 | 
				
			||||||
    <Compile Include="Constants\ShowWindowCommand.cs" />
 | 
					    <Compile Include="Constants\ShowWindowCommand.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										25
									
								
								SafeExamBrowser.WindowsApi/Types/EXECUTION_STATE.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								SafeExamBrowser.WindowsApi/Types/EXECUTION_STATE.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace SafeExamBrowser.WindowsApi.Types
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/// <remarks>
 | 
				
			||||||
 | 
						/// See http://www.pinvoke.net/default.aspx/kernel32/SetThreadExecutionState.html.
 | 
				
			||||||
 | 
						/// See https://msdn.microsoft.com/en-us/library/aa373208(v=vs.85).aspx.
 | 
				
			||||||
 | 
						/// </remarks>
 | 
				
			||||||
 | 
						[Flags]
 | 
				
			||||||
 | 
						public enum EXECUTION_STATE : uint
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							AWAYMODE_REQUIRED = 0x00000040,
 | 
				
			||||||
 | 
							CONTINUOUS = 0x80000000,
 | 
				
			||||||
 | 
							DISPLAY_REQUIRED = 0x00000002,
 | 
				
			||||||
 | 
							SYSTEM_REQUIRED = 0x00000001
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -11,9 +11,9 @@ using SafeExamBrowser.Contracts.WindowsApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SafeExamBrowser.WindowsApi.Types
 | 
					namespace SafeExamBrowser.WindowsApi.Types
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/// <summary>
 | 
						/// <remarks>
 | 
				
			||||||
	/// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx.
 | 
						/// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx.
 | 
				
			||||||
	/// </summary>
 | 
						/// </remarks>
 | 
				
			||||||
	[StructLayout(LayoutKind.Sequential)]
 | 
						[StructLayout(LayoutKind.Sequential)]
 | 
				
			||||||
	internal struct RECT
 | 
						internal struct RECT
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,10 +38,10 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
		[return: MarshalAs(UnmanagedType.Bool)]
 | 
							[return: MarshalAs(UnmanagedType.Bool)]
 | 
				
			||||||
		internal static extern bool EnumWindows(EnumWindowsDelegate enumProc, IntPtr lParam);
 | 
							internal static extern bool EnumWindows(EnumWindowsDelegate enumProc, IntPtr lParam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport("user32.dll", SetLastError = true)]
 | 
							[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 | 
				
			||||||
		internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 | 
							internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 | 
							[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 | 
				
			||||||
		internal static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
 | 
							internal static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport("user32.dll", SetLastError = true)]
 | 
							[DllImport("user32.dll", SetLastError = true)]
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,10 @@ namespace SafeExamBrowser.WindowsApi
 | 
				
			||||||
		[return: MarshalAs(UnmanagedType.Bool)]
 | 
							[return: MarshalAs(UnmanagedType.Bool)]
 | 
				
			||||||
		internal static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref RECT pvParam, SPIF fWinIni);
 | 
							internal static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref RECT pvParam, SPIF fWinIni);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 | 
				
			||||||
 | 
							[return: MarshalAs(UnmanagedType.Bool)]
 | 
				
			||||||
 | 
							internal static extern bool SystemParametersInfo(SPI uiAction, int uiParam, string pvParam, SPIF fWinIni);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[DllImport("user32.dll", SetLastError = true)]
 | 
							[DllImport("user32.dll", SetLastError = true)]
 | 
				
			||||||
		internal static extern bool UnhookWinEvent(IntPtr hWinEventHook);
 | 
							internal static extern bool UnhookWinEvent(IntPtr hWinEventHook);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@ using SafeExamBrowser.Core.Behaviour;
 | 
				
			||||||
using SafeExamBrowser.Core.Behaviour.Operations;
 | 
					using SafeExamBrowser.Core.Behaviour.Operations;
 | 
				
			||||||
using SafeExamBrowser.Core.I18n;
 | 
					using SafeExamBrowser.Core.I18n;
 | 
				
			||||||
using SafeExamBrowser.Core.Logging;
 | 
					using SafeExamBrowser.Core.Logging;
 | 
				
			||||||
 | 
					using SafeExamBrowser.Monitoring.Display;
 | 
				
			||||||
using SafeExamBrowser.Monitoring.Keyboard;
 | 
					using SafeExamBrowser.Monitoring.Keyboard;
 | 
				
			||||||
using SafeExamBrowser.Monitoring.Mouse;
 | 
					using SafeExamBrowser.Monitoring.Mouse;
 | 
				
			||||||
using SafeExamBrowser.Monitoring.Processes;
 | 
					using SafeExamBrowser.Monitoring.Processes;
 | 
				
			||||||
| 
						 | 
					@ -34,6 +35,7 @@ namespace SafeExamBrowser
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		private IApplicationController browserController;
 | 
							private IApplicationController browserController;
 | 
				
			||||||
		private IApplicationInfo browserInfo;
 | 
							private IApplicationInfo browserInfo;
 | 
				
			||||||
 | 
							private IDisplayMonitor displayMonitor;
 | 
				
			||||||
		private IKeyboardInterceptor keyboardInterceptor;
 | 
							private IKeyboardInterceptor keyboardInterceptor;
 | 
				
			||||||
		private ILogger logger;
 | 
							private ILogger logger;
 | 
				
			||||||
		private ILogContentFormatter logFormatter;
 | 
							private ILogContentFormatter logFormatter;
 | 
				
			||||||
| 
						 | 
					@ -46,7 +48,6 @@ namespace SafeExamBrowser
 | 
				
			||||||
		private ITextResource textResource;
 | 
							private ITextResource textResource;
 | 
				
			||||||
		private IUserInterfaceFactory uiFactory;
 | 
							private IUserInterfaceFactory uiFactory;
 | 
				
			||||||
		private IWindowMonitor windowMonitor;
 | 
							private IWindowMonitor windowMonitor;
 | 
				
			||||||
		private IWorkingArea workingArea;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IShutdownController ShutdownController { get; private set; }
 | 
							public IShutdownController ShutdownController { get; private set; }
 | 
				
			||||||
		public IStartupController StartupController { get; private set; }
 | 
							public IStartupController StartupController { get; private set; }
 | 
				
			||||||
| 
						 | 
					@ -59,22 +60,22 @@ namespace SafeExamBrowser
 | 
				
			||||||
			logger = new Logger();
 | 
								logger = new Logger();
 | 
				
			||||||
			logFormatter = new DefaultLogFormatter();
 | 
								logFormatter = new DefaultLogFormatter();
 | 
				
			||||||
			nativeMethods = new NativeMethods();
 | 
								nativeMethods = new NativeMethods();
 | 
				
			||||||
			settings = new SettingsImpl();
 | 
								settings = new Settings();
 | 
				
			||||||
			Taskbar = new Taskbar();
 | 
					 | 
				
			||||||
			textResource = new XmlTextResource();
 | 
								textResource = new XmlTextResource();
 | 
				
			||||||
			uiFactory = new UserInterfaceFactory();
 | 
								uiFactory = new UserInterfaceFactory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			logger.Subscribe(new LogFileWriter(logFormatter, settings));
 | 
								logger.Subscribe(new LogFileWriter(logFormatter, settings));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			text = new Text(textResource);
 | 
								text = new Text(textResource);
 | 
				
			||||||
 | 
								Taskbar = new Taskbar(new ModuleLogger(logger, typeof(Taskbar)));
 | 
				
			||||||
			browserController = new BrowserApplicationController(settings, text, uiFactory);
 | 
								browserController = new BrowserApplicationController(settings, text, uiFactory);
 | 
				
			||||||
 | 
								displayMonitor = new DisplayMonitor(new ModuleLogger(logger, typeof(DisplayMonitor)), nativeMethods);
 | 
				
			||||||
			keyboardInterceptor = new KeyboardInterceptor(settings.Keyboard, new ModuleLogger(logger, typeof(KeyboardInterceptor)));
 | 
								keyboardInterceptor = new KeyboardInterceptor(settings.Keyboard, new ModuleLogger(logger, typeof(KeyboardInterceptor)));
 | 
				
			||||||
			mouseInterceptor = new MouseInterceptor(new ModuleLogger(logger, typeof(MouseInterceptor)), settings.Mouse);
 | 
								mouseInterceptor = new MouseInterceptor(new ModuleLogger(logger, typeof(MouseInterceptor)), settings.Mouse);
 | 
				
			||||||
			processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
 | 
								processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
 | 
				
			||||||
			windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
 | 
								windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
 | 
				
			||||||
			workingArea = new WorkingArea(new ModuleLogger(logger, typeof(WorkingArea)), nativeMethods);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			runtimeController = new RuntimeController(new ModuleLogger(logger, typeof(RuntimeController)), processMonitor, Taskbar, windowMonitor, workingArea);
 | 
								runtimeController = new RuntimeController(displayMonitor, new ModuleLogger(logger, typeof(RuntimeController)), processMonitor, Taskbar, windowMonitor);
 | 
				
			||||||
			ShutdownController = new ShutdownController(logger, settings, text, uiFactory);
 | 
								ShutdownController = new ShutdownController(logger, settings, text, uiFactory);
 | 
				
			||||||
			StartupController = new StartupController(logger, settings, text, uiFactory);
 | 
								StartupController = new StartupController(logger, settings, text, uiFactory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +83,7 @@ namespace SafeExamBrowser
 | 
				
			||||||
			StartupOperations.Enqueue(new KeyboardInterceptorOperation(keyboardInterceptor, logger, nativeMethods));
 | 
								StartupOperations.Enqueue(new KeyboardInterceptorOperation(keyboardInterceptor, logger, nativeMethods));
 | 
				
			||||||
			StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
 | 
								StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
 | 
				
			||||||
			StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
 | 
								StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
 | 
				
			||||||
			StartupOperations.Enqueue(new WorkingAreaOperation(logger, Taskbar, workingArea));
 | 
								StartupOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, Taskbar));
 | 
				
			||||||
			StartupOperations.Enqueue(new TaskbarOperation(logger, logFormatter, settings, Taskbar, text, uiFactory));
 | 
								StartupOperations.Enqueue(new TaskbarOperation(logger, logFormatter, settings, Taskbar, text, uiFactory));
 | 
				
			||||||
			StartupOperations.Enqueue(new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
 | 
								StartupOperations.Enqueue(new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
 | 
				
			||||||
			StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, logger));
 | 
								StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, logger));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue