Implemented basic keyboard monitoring.
This commit is contained in:
		
							parent
							
								
									32980f9f97
								
							
						
					
					
						commit
						a79f0c6d77
					
				
					 17 changed files with 273 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -62,6 +62,7 @@
 | 
			
		|||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Bounds.cs" />
 | 
			
		||||
    <Compile Include="Settings\BrowserSettings.cs" />
 | 
			
		||||
    <Compile Include="Settings\KeyboardSettings.cs" />
 | 
			
		||||
    <Compile Include="Settings\SettingsImpl.cs" />
 | 
			
		||||
    <Compile Include="WorkingArea.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								SafeExamBrowser.Configuration/Settings/KeyboardSettings.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								SafeExamBrowser.Configuration/Settings/KeyboardSettings.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.Configuration.Settings;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Configuration.Settings
 | 
			
		||||
{
 | 
			
		||||
	public class KeyboardSettings : IKeyboardSettings
 | 
			
		||||
	{
 | 
			
		||||
		public bool AllowAltTab => false;
 | 
			
		||||
 | 
			
		||||
		public bool AllowEsc => false;
 | 
			
		||||
 | 
			
		||||
		public bool AllowF5 => true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ namespace SafeExamBrowser.Configuration
 | 
			
		|||
		public SettingsImpl()
 | 
			
		||||
		{
 | 
			
		||||
			Browser = new BrowserSettings(this);
 | 
			
		||||
			Keyboard = new KeyboardSettings();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string AppDataFolderName => "SafeExamBrowser";
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,8 @@ namespace SafeExamBrowser.Configuration
 | 
			
		|||
 | 
			
		||||
		public IBrowserSettings Browser { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public IKeyboardSettings Keyboard { get; private set; }
 | 
			
		||||
 | 
			
		||||
		public string LogFolderPath
 | 
			
		||||
		{
 | 
			
		||||
			get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), AppDataFolderName, "Logs"); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.Configuration.Settings
 | 
			
		||||
{
 | 
			
		||||
	public interface IKeyboardSettings
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Determines whether the user may use the ALT+TAB shortcut.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool AllowAltTab { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Determines whether the user may use the escape key.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool AllowEsc { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Determines whether the user may use the F5 key.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool AllowF5 { get; }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
 | 
			
		|||
		/// </summary>
 | 
			
		||||
		IBrowserSettings Browser { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// All keyboard-related settings.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		IKeyboardSettings Keyboard { get; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The path where the log files are to be stored.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,8 +11,8 @@ namespace SafeExamBrowser.Contracts.Monitoring
 | 
			
		|||
	public interface IKeyboardInterceptor
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns <c>true</c> if the given key should be blocked, otherwise <c>false</c>.
 | 
			
		||||
		/// Returns <c>true</c> if the given key should be blocked, otherwise <c>false</c>. The key code corresponds to a Win32 Virtual-Key.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool Block(uint keyCode, KeyModifier modifier);
 | 
			
		||||
		bool Block(int keyCode, KeyModifier modifier, KeyState state);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ namespace SafeExamBrowser.Contracts.Monitoring
 | 
			
		|||
	public enum KeyModifier
 | 
			
		||||
	{
 | 
			
		||||
		None = 0,
 | 
			
		||||
		Ctrl = 0b01,
 | 
			
		||||
		Alt = 0b10
 | 
			
		||||
		Alt = 0b1,
 | 
			
		||||
		Ctrl = 0b10
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								SafeExamBrowser.Contracts/Monitoring/KeyState.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								SafeExamBrowser.Contracts/Monitoring/KeyState.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 enum KeyState
 | 
			
		||||
	{
 | 
			
		||||
		None = 0,
 | 
			
		||||
		Pressed,
 | 
			
		||||
		Released
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +67,7 @@
 | 
			
		|||
    <Compile Include="Configuration\IApplicationInstance.cs" />
 | 
			
		||||
    <Compile Include="Configuration\INotificationInfo.cs" />
 | 
			
		||||
    <Compile Include="Configuration\Settings\IBrowserSettings.cs" />
 | 
			
		||||
    <Compile Include="Configuration\Settings\IKeyboardSettings.cs" />
 | 
			
		||||
    <Compile Include="Configuration\Settings\ISettings.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\IShutdownController.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\IStartupController.cs" />
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +86,7 @@
 | 
			
		|||
    <Compile Include="Monitoring\IProcessMonitor.cs" />
 | 
			
		||||
    <Compile Include="Monitoring\IWindowMonitor.cs" />
 | 
			
		||||
    <Compile Include="Monitoring\KeyModifier.cs" />
 | 
			
		||||
    <Compile Include="Monitoring\KeyState.cs" />
 | 
			
		||||
    <Compile Include="UserInterface\IBrowserControl.cs" />
 | 
			
		||||
    <Compile Include="UserInterface\IBrowserWindow.cs" />
 | 
			
		||||
    <Compile Include="UserInterface\IMessageBox.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.Behaviour;
 | 
			
		||||
using SafeExamBrowser.Contracts.Logging;
 | 
			
		||||
using SafeExamBrowser.Contracts.Monitoring;
 | 
			
		||||
using SafeExamBrowser.Contracts.UserInterface;
 | 
			
		||||
using SafeExamBrowser.Contracts.WindowsApi;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Core.Behaviour.Operations
 | 
			
		||||
{
 | 
			
		||||
	public class DeviceInterceptionOperation : IOperation
 | 
			
		||||
	{
 | 
			
		||||
		private IKeyboardInterceptor keyboardInterceptor;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private INativeMethods nativeMethods;
 | 
			
		||||
 | 
			
		||||
		public ISplashScreen SplashScreen { private get; set; }
 | 
			
		||||
		
 | 
			
		||||
		public DeviceInterceptionOperation(IKeyboardInterceptor keyboardInterceptor, ILogger logger, INativeMethods nativeMethods)
 | 
			
		||||
		{
 | 
			
		||||
			this.keyboardInterceptor = keyboardInterceptor;
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.nativeMethods = nativeMethods;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Perform()
 | 
			
		||||
		{
 | 
			
		||||
			logger.Info("Starting keyboard and mouse interception...");
 | 
			
		||||
 | 
			
		||||
			nativeMethods.RegisterKeyboardHook(keyboardInterceptor);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Revert()
 | 
			
		||||
		{
 | 
			
		||||
			logger.Info("Stopping keyboard and mouse interception...");
 | 
			
		||||
 | 
			
		||||
			nativeMethods.UnregisterKeyboardHook(keyboardInterceptor);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +58,7 @@
 | 
			
		|||
    <Reference Include="System.Xml" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Behaviour\Operations\DeviceInterceptionOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\RuntimeController.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\BrowserOperation.cs" />
 | 
			
		||||
    <Compile Include="Behaviour\Operations\EventControllerOperation.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										72
									
								
								SafeExamBrowser.Monitoring/Keyboard/KeyboardInterceptor.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								SafeExamBrowser.Monitoring/Keyboard/KeyboardInterceptor.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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.Linq;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using SafeExamBrowser.Contracts.Configuration.Settings;
 | 
			
		||||
using SafeExamBrowser.Contracts.Logging;
 | 
			
		||||
using SafeExamBrowser.Contracts.Monitoring;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Monitoring.Keyboard
 | 
			
		||||
{
 | 
			
		||||
	public class KeyboardInterceptor : IKeyboardInterceptor
 | 
			
		||||
	{
 | 
			
		||||
		private IKeyboardSettings settings;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
 | 
			
		||||
		public KeyboardInterceptor(IKeyboardSettings settings, ILogger logger)
 | 
			
		||||
		{
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.settings = settings;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool Block(int keyCode, KeyModifier modifier, KeyState state)
 | 
			
		||||
		{
 | 
			
		||||
			var block = false;
 | 
			
		||||
			var key = KeyInterop.KeyFromVirtualKey(keyCode);
 | 
			
		||||
 | 
			
		||||
			block |= key == Key.Apps;
 | 
			
		||||
			block |= key == Key.F1;
 | 
			
		||||
			block |= key == Key.F2;
 | 
			
		||||
			block |= key == Key.F3;
 | 
			
		||||
			block |= key == Key.F4;
 | 
			
		||||
			block |= key == Key.F6;
 | 
			
		||||
			block |= key == Key.F7;
 | 
			
		||||
			block |= key == Key.F8;
 | 
			
		||||
			block |= key == Key.F9;
 | 
			
		||||
			block |= key == Key.F10;
 | 
			
		||||
			block |= key == Key.F11;
 | 
			
		||||
			block |= key == Key.F12;
 | 
			
		||||
			block |= key == Key.PrintScreen;
 | 
			
		||||
 | 
			
		||||
			block |= key == Key.Escape && modifier.HasFlag(KeyModifier.Alt);
 | 
			
		||||
			block |= key == Key.Escape && modifier.HasFlag(KeyModifier.Ctrl);
 | 
			
		||||
			block |= key == Key.Space && modifier.HasFlag(KeyModifier.Alt);
 | 
			
		||||
 | 
			
		||||
			block |= !settings.AllowAltTab && key == Key.Tab && modifier.HasFlag(KeyModifier.Alt);
 | 
			
		||||
			block |= !settings.AllowEsc && key == Key.Escape && modifier == KeyModifier.None;
 | 
			
		||||
			block |= !settings.AllowF5 && key == Key.F5;
 | 
			
		||||
 | 
			
		||||
			if (block)
 | 
			
		||||
			{
 | 
			
		||||
				Log(key, keyCode, modifier, state);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return block;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void Log(Key key, int keyCode, KeyModifier modifier, KeyState state)
 | 
			
		||||
		{
 | 
			
		||||
			var modifierFlags = Enum.GetValues(typeof(KeyModifier)).OfType<KeyModifier>().Where(m => m != KeyModifier.None && modifier.HasFlag(m));
 | 
			
		||||
			var modifiers = modifierFlags.Any() ? String.Join(" + ", modifierFlags) + " + " : string.Empty;
 | 
			
		||||
 | 
			
		||||
			logger.Info($"Blocked '{modifiers}{key}' ({key} = {keyCode}) when {state.ToString().ToLower()}.");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -57,8 +57,10 @@
 | 
			
		|||
    <Reference Include="System.Data" />
 | 
			
		||||
    <Reference Include="System.Net.Http" />
 | 
			
		||||
    <Reference Include="System.Xml" />
 | 
			
		||||
    <Reference Include="WindowsBase" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Keyboard\KeyboardInterceptor.cs" />
 | 
			
		||||
    <Compile Include="Processes\ProcessMonitor.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
			
		||||
    <Compile Include="Windows\WindowMonitor.cs" />
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +72,6 @@
 | 
			
		|||
    </ProjectReference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="Keyboard\" />
 | 
			
		||||
    <Folder Include="Mouse\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ namespace SafeExamBrowser.WindowsApi.Constants
 | 
			
		|||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Posted to the window with the keyboard focus when a nonsystem key is released. A nonsystem key is a key that is pressed when
 | 
			
		||||
		/// the ALT key is not pressed, or a keyboard key that is pressed when a window has the keyboard focus. 
 | 
			
		||||
		/// the ALT key is not pressed, or a keyboard key that is pressed when a window has the keyboard focus.
 | 
			
		||||
		/// 
 | 
			
		||||
		/// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646281(v=vs.85).aspx.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,15 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
 | 
			
		|||
{
 | 
			
		||||
	internal class KeyboardHook
 | 
			
		||||
	{
 | 
			
		||||
		private const int LEFT_CTRL = 162;
 | 
			
		||||
		private const int RIGHT_CTRL = 163;
 | 
			
		||||
		private const int LEFT_ALT = 164;
 | 
			
		||||
		private const int RIGHT_ALT = 165;
 | 
			
		||||
		private const int DELETE = 46;
 | 
			
		||||
 | 
			
		||||
		private bool altPressed, ctrlPressed;
 | 
			
		||||
		private HookProc hookProc;
 | 
			
		||||
 | 
			
		||||
		internal IntPtr Handle { get; private set; }
 | 
			
		||||
		internal IKeyboardInterceptor Interceptor { get; private set; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +37,12 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
 | 
			
		|||
		{
 | 
			
		||||
			var module = Kernel32.GetModuleHandle(null);
 | 
			
		||||
 | 
			
		||||
			Handle = User32.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, LowLevelKeyboardProc, module, 0);
 | 
			
		||||
			// IMORTANT:
 | 
			
		||||
			// Ensures that the hook delegate does not get garbage collected prematurely, as it will be passed to unmanaged code.
 | 
			
		||||
			// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
 | 
			
		||||
			hookProc = new HookProc(LowLevelKeyboardProc);
 | 
			
		||||
 | 
			
		||||
			Handle = User32.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, hookProc, module, 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal bool Detach()
 | 
			
		||||
| 
						 | 
				
			
			@ -40,10 +54,11 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
 | 
			
		|||
		{
 | 
			
		||||
			if (nCode >= 0)
 | 
			
		||||
			{
 | 
			
		||||
				var state = GetState(wParam.ToInt32());
 | 
			
		||||
				var keyData = (KBDLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
 | 
			
		||||
				var modifier = GetModifiers(keyData);
 | 
			
		||||
				var modifier = GetModifiers(keyData, wParam.ToInt32());
 | 
			
		||||
 | 
			
		||||
				if (Interceptor.Block(keyData.KeyCode, modifier))
 | 
			
		||||
				if (Interceptor.Block((int) keyData.KeyCode, modifier, state))
 | 
			
		||||
				{
 | 
			
		||||
					return (IntPtr) 1;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -52,21 +67,64 @@ namespace SafeExamBrowser.WindowsApi.Monitoring
 | 
			
		|||
			return User32.CallNextHookEx(Handle, nCode, wParam, lParam);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private KeyModifier GetModifiers(KBDLLHOOKSTRUCT keyData)
 | 
			
		||||
		private KeyState GetState(int wParam)
 | 
			
		||||
		{
 | 
			
		||||
			switch (wParam)
 | 
			
		||||
			{
 | 
			
		||||
				case Constant.WM_KEYDOWN:
 | 
			
		||||
				case Constant.WM_SYSKEYDOWN:
 | 
			
		||||
					return KeyState.Pressed;
 | 
			
		||||
				case Constant.WM_KEYUP:
 | 
			
		||||
				case Constant.WM_SYSKEYUP:
 | 
			
		||||
					return KeyState.Released;
 | 
			
		||||
				default:
 | 
			
		||||
					return KeyState.None;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private KeyModifier GetModifiers(KBDLLHOOKSTRUCT keyData, int wParam)
 | 
			
		||||
		{
 | 
			
		||||
			var modifier = KeyModifier.None;
 | 
			
		||||
 | 
			
		||||
			if ((keyData.Flags & KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN) == KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN)
 | 
			
		||||
			TrackCtrlAndAlt(keyData, wParam);
 | 
			
		||||
 | 
			
		||||
			if (altPressed || keyData.Flags.HasFlag(KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN))
 | 
			
		||||
			{
 | 
			
		||||
				modifier |= KeyModifier.Alt;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (keyData.Flags == 0)
 | 
			
		||||
			if (ctrlPressed)
 | 
			
		||||
			{
 | 
			
		||||
				modifier |= KeyModifier.Ctrl;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return modifier;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void TrackCtrlAndAlt(KBDLLHOOKSTRUCT keyData, int wParam)
 | 
			
		||||
		{
 | 
			
		||||
			var keyCode = keyData.KeyCode;
 | 
			
		||||
 | 
			
		||||
			if (keyCode == LEFT_CTRL || keyCode == RIGHT_CTRL)
 | 
			
		||||
			{
 | 
			
		||||
				ctrlPressed = IsPressed(wParam);
 | 
			
		||||
			}
 | 
			
		||||
			else if (keyCode == LEFT_ALT || keyCode == RIGHT_ALT)
 | 
			
		||||
			{
 | 
			
		||||
				altPressed = IsPressed(wParam);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (ctrlPressed && altPressed && keyCode == DELETE)
 | 
			
		||||
			{
 | 
			
		||||
				// When the Secure Attention Sequence is pressed, the WM_KEYUP / WM_SYSKEYUP messages for CTRL and ALT get lost...
 | 
			
		||||
				ctrlPressed = false;
 | 
			
		||||
				altPressed = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool IsPressed(int wParam)
 | 
			
		||||
		{
 | 
			
		||||
			return wParam == Constant.WM_KEYDOWN || wParam == Constant.WM_SYSKEYDOWN;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ namespace SafeExamBrowser.WindowsApi
 | 
			
		|||
		private ConcurrentDictionary<IntPtr, KeyboardHook> KeyboardHooks = new ConcurrentDictionary<IntPtr, KeyboardHook>();
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Upon finalization, unregister all system events and hooks...
 | 
			
		||||
		/// Upon finalization, unregister all active system events and hooks...
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		~NativeMethods()
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -144,9 +144,6 @@ namespace SafeExamBrowser.WindowsApi
 | 
			
		|||
 | 
			
		||||
			hook.Attach();
 | 
			
		||||
 | 
			
		||||
			// IMORTANT:
 | 
			
		||||
			// Ensures that the hook does not get garbage collected prematurely, as it will be passed to unmanaged code.
 | 
			
		||||
			// Not doing so will result in a <c>CallbackOnCollectedDelegate</c> error and subsequent application crash!
 | 
			
		||||
			KeyboardHooks[hook.Handle] = hook;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ using SafeExamBrowser.Core.Behaviour;
 | 
			
		|||
using SafeExamBrowser.Core.Behaviour.Operations;
 | 
			
		||||
using SafeExamBrowser.Core.I18n;
 | 
			
		||||
using SafeExamBrowser.Core.Logging;
 | 
			
		||||
using SafeExamBrowser.Monitoring.Keyboard;
 | 
			
		||||
using SafeExamBrowser.Monitoring.Processes;
 | 
			
		||||
using SafeExamBrowser.Monitoring.Windows;
 | 
			
		||||
using SafeExamBrowser.UserInterface;
 | 
			
		||||
| 
						 | 
				
			
			@ -32,10 +33,11 @@ namespace SafeExamBrowser
 | 
			
		|||
	{
 | 
			
		||||
		private IApplicationController browserController;
 | 
			
		||||
		private IApplicationInfo browserInfo;
 | 
			
		||||
		private IRuntimeController runtimeController;
 | 
			
		||||
		private IKeyboardInterceptor keyboardInterceptor;
 | 
			
		||||
		private ILogger logger;
 | 
			
		||||
		private INativeMethods nativeMethods;
 | 
			
		||||
		private IProcessMonitor processMonitor;
 | 
			
		||||
		private IRuntimeController runtimeController;
 | 
			
		||||
		private ISettings settings;
 | 
			
		||||
		private IText text;
 | 
			
		||||
		private ITextResource textResource;
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,7 @@ namespace SafeExamBrowser
 | 
			
		|||
 | 
			
		||||
			text = new Text(textResource);
 | 
			
		||||
			browserController = new BrowserApplicationController(settings, text, uiFactory);
 | 
			
		||||
			keyboardInterceptor = new KeyboardInterceptor(settings.Keyboard, new ModuleLogger(logger, typeof(KeyboardInterceptor)));
 | 
			
		||||
			processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
 | 
			
		||||
			windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
 | 
			
		||||
			workingArea = new WorkingArea(new ModuleLogger(logger, typeof(WorkingArea)), nativeMethods);
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +74,7 @@ namespace SafeExamBrowser
 | 
			
		|||
			StartupController = new StartupController(logger, settings, text, uiFactory);
 | 
			
		||||
 | 
			
		||||
			StartupOperations = new Queue<IOperation>();
 | 
			
		||||
			StartupOperations.Enqueue(new DeviceInterceptionOperation(keyboardInterceptor, logger, nativeMethods));
 | 
			
		||||
			StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
 | 
			
		||||
			StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
 | 
			
		||||
			StartupOperations.Enqueue(new WorkingAreaOperation(logger, Taskbar, workingArea));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue