SEBWIN-732: Implemented random desktop functionality.
This commit is contained in:
parent
3711555f70
commit
026d1fbfd8
11 changed files with 116 additions and 38 deletions
|
@ -54,6 +54,7 @@ using SafeExamBrowser.UserInterface.Contracts.Shell;
|
|||
using SafeExamBrowser.UserInterface.Shared.Activators;
|
||||
using SafeExamBrowser.WindowsApi;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Processes;
|
||||
using Desktop = SafeExamBrowser.UserInterface.Desktop;
|
||||
using Mobile = SafeExamBrowser.UserInterface.Mobile;
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ using SafeExamBrowser.SystemComponents.Contracts;
|
|||
using SafeExamBrowser.SystemComponents.Registry;
|
||||
using SafeExamBrowser.UserInterface.Desktop;
|
||||
using SafeExamBrowser.WindowsApi;
|
||||
using SafeExamBrowser.WindowsApi.Desktops;
|
||||
using SafeExamBrowser.WindowsApi.Processes;
|
||||
|
||||
namespace SafeExamBrowser.Runtime
|
||||
{
|
||||
|
|
|
@ -17,14 +17,15 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
{
|
||||
internal class KioskModeOperation : SessionOperation
|
||||
{
|
||||
private IDesktop newDesktop;
|
||||
private IDesktop originalDesktop;
|
||||
private IDesktopFactory desktopFactory;
|
||||
private IDesktopMonitor desktopMonitor;
|
||||
private IExplorerShell explorerShell;
|
||||
private readonly IDesktopFactory desktopFactory;
|
||||
private readonly IDesktopMonitor desktopMonitor;
|
||||
private readonly IExplorerShell explorerShell;
|
||||
private readonly ILogger logger;
|
||||
private readonly IProcessFactory processFactory;
|
||||
|
||||
private KioskMode? activeMode;
|
||||
private ILogger logger;
|
||||
private IProcessFactory processFactory;
|
||||
private IDesktop customDesktop;
|
||||
private IDesktop originalDesktop;
|
||||
|
||||
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
public override event StatusChangedEventHandler StatusChanged;
|
||||
|
@ -54,7 +55,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
switch (Context.Next.Settings.Security.KioskMode)
|
||||
{
|
||||
case KioskMode.CreateNewDesktop:
|
||||
CreateNewDesktop();
|
||||
CreateCustomDesktop();
|
||||
break;
|
||||
case KioskMode.DisableExplorerShell:
|
||||
TerminateExplorerShell();
|
||||
|
@ -80,7 +81,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
switch (activeMode)
|
||||
{
|
||||
case KioskMode.CreateNewDesktop:
|
||||
CloseNewDesktop();
|
||||
CloseCustomDesktop();
|
||||
break;
|
||||
case KioskMode.DisableExplorerShell:
|
||||
RestartExplorerShell();
|
||||
|
@ -92,7 +93,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
switch (newMode)
|
||||
{
|
||||
case KioskMode.CreateNewDesktop:
|
||||
CreateNewDesktop();
|
||||
CreateCustomDesktop();
|
||||
break;
|
||||
case KioskMode.DisableExplorerShell:
|
||||
TerminateExplorerShell();
|
||||
|
@ -111,7 +112,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
switch (activeMode)
|
||||
{
|
||||
case KioskMode.CreateNewDesktop:
|
||||
CloseNewDesktop();
|
||||
CloseCustomDesktop();
|
||||
break;
|
||||
case KioskMode.DisableExplorerShell:
|
||||
RestartExplorerShell();
|
||||
|
@ -121,26 +122,26 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private void CreateNewDesktop()
|
||||
private void CreateCustomDesktop()
|
||||
{
|
||||
originalDesktop = desktopFactory.GetCurrent();
|
||||
logger.Info($"Current desktop is {originalDesktop}.");
|
||||
|
||||
newDesktop = desktopFactory.CreateNew(nameof(SafeExamBrowser));
|
||||
logger.Info($"Created new desktop {newDesktop}.");
|
||||
customDesktop = desktopFactory.CreateRandom();
|
||||
logger.Info($"Created custom desktop {customDesktop}.");
|
||||
|
||||
newDesktop.Activate();
|
||||
processFactory.StartupDesktop = newDesktop;
|
||||
logger.Info("Successfully activated new desktop.");
|
||||
customDesktop.Activate();
|
||||
processFactory.StartupDesktop = customDesktop;
|
||||
logger.Info("Successfully activated custom desktop.");
|
||||
|
||||
desktopMonitor.Start(newDesktop);
|
||||
desktopMonitor.Start(customDesktop);
|
||||
}
|
||||
|
||||
private void CloseNewDesktop()
|
||||
private void CloseCustomDesktop()
|
||||
{
|
||||
desktopMonitor.Stop();
|
||||
|
||||
if (originalDesktop != null)
|
||||
if (originalDesktop != default)
|
||||
{
|
||||
originalDesktop.Activate();
|
||||
processFactory.StartupDesktop = originalDesktop;
|
||||
|
@ -151,14 +152,14 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
logger.Warn($"No original desktop found to activate!");
|
||||
}
|
||||
|
||||
if (newDesktop != null)
|
||||
if (customDesktop != default)
|
||||
{
|
||||
newDesktop.Close();
|
||||
logger.Info($"Closed new desktop {newDesktop}.");
|
||||
customDesktop.Close();
|
||||
logger.Info($"Closed custom desktop {customDesktop}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn($"No new desktop found to close!");
|
||||
logger.Warn($"No custom desktop found to close!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ namespace SafeExamBrowser.WindowsApi.Contracts
|
|||
/// <exception cref="System.ComponentModel.Win32Exception">If the desktop could not be created.</exception>
|
||||
IDesktop CreateNew(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new desktop with a random name.
|
||||
/// </summary>
|
||||
/// <exception cref="System.ComponentModel.Win32Exception">If the desktop could not be created.</exception>
|
||||
IDesktop CreateRandom();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the currently active desktop.
|
||||
/// </summary>
|
||||
|
|
|
@ -11,9 +11,9 @@ using System.ComponentModel;
|
|||
using System.Runtime.InteropServices;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
namespace SafeExamBrowser.WindowsApi.Desktops
|
||||
{
|
||||
public class Desktop : IDesktop
|
||||
internal class Desktop : IDesktop
|
||||
{
|
||||
public IntPtr Handle { get; private set; }
|
||||
public string Name { get; private set; }
|
|
@ -10,18 +10,20 @@ using System;
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
namespace SafeExamBrowser.WindowsApi.Desktops
|
||||
{
|
||||
public class DesktopFactory : IDesktopFactory
|
||||
{
|
||||
private ILogger logger;
|
||||
private readonly ILogger logger;
|
||||
private readonly Random random;
|
||||
|
||||
public DesktopFactory(ILogger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
public IDesktop CreateNew(string name)
|
||||
|
@ -44,11 +46,34 @@ namespace SafeExamBrowser.WindowsApi
|
|||
return desktop;
|
||||
}
|
||||
|
||||
public IDesktop CreateRandom()
|
||||
{
|
||||
logger.Debug($"Attempting to create random desktop...");
|
||||
|
||||
var name = GenerateRandomDesktopName();
|
||||
var handle = User32.CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0, (uint) AccessMask.GENERIC_ALL, IntPtr.Zero);
|
||||
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
logger.Error($"Failed to create random desktop '{name}'!");
|
||||
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
var obfuscatedHandle = new IntPtr(random.Next(100, 10000));
|
||||
var obfuscatedName = GenerateRandomDesktopName();
|
||||
var desktop = new ObfuscatedDesktop(handle, name, obfuscatedHandle, obfuscatedName);
|
||||
|
||||
logger.Debug($"Successfully created random desktop {desktop}.");
|
||||
|
||||
return desktop;
|
||||
}
|
||||
|
||||
public IDesktop GetCurrent()
|
||||
{
|
||||
var threadId = Kernel32.GetCurrentThreadId();
|
||||
var handle = User32.GetThreadDesktop(threadId);
|
||||
var name = String.Empty;
|
||||
var name = string.Empty;
|
||||
var nameLength = 0;
|
||||
|
||||
if (handle == IntPtr.Zero)
|
||||
|
@ -81,5 +106,18 @@ namespace SafeExamBrowser.WindowsApi
|
|||
|
||||
return desktop;
|
||||
}
|
||||
|
||||
private string GenerateRandomDesktopName()
|
||||
{
|
||||
var length = random.Next(5, 20);
|
||||
var name = new char[length];
|
||||
|
||||
for (var letter = 0; letter < length; letter++)
|
||||
{
|
||||
name[letter] = (char) (random.Next(2) == 0 && letter != 0 ? random.Next('a', 'z' + 1) : random.Next('A', 'Z' + 1));
|
||||
}
|
||||
|
||||
return new string(name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ using SafeExamBrowser.Logging.Contracts;
|
|||
using SafeExamBrowser.WindowsApi.Constants;
|
||||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
namespace SafeExamBrowser.WindowsApi.Desktops
|
||||
{
|
||||
public class DesktopMonitor : IDesktopMonitor
|
||||
{
|
29
SafeExamBrowser.WindowsApi/Desktops/ObfuscatedDesktop.cs
Normal file
29
SafeExamBrowser.WindowsApi/Desktops/ObfuscatedDesktop.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.Desktops
|
||||
{
|
||||
internal class ObfuscatedDesktop : Desktop
|
||||
{
|
||||
private readonly IntPtr? obfuscatedHandle;
|
||||
private readonly string obfuscatedName;
|
||||
|
||||
public ObfuscatedDesktop(IntPtr handle, string name, IntPtr? obfuscatedHandle, string obfuscatedName) : base(handle, name)
|
||||
{
|
||||
this.obfuscatedHandle = obfuscatedHandle;
|
||||
this.obfuscatedName = obfuscatedName;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"'{obfuscatedName}' [{obfuscatedHandle}]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ using SafeExamBrowser.Logging.Contracts;
|
|||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
namespace SafeExamBrowser.WindowsApi.Processes
|
||||
{
|
||||
internal class Process : IProcess
|
||||
{
|
|
@ -20,7 +20,7 @@ using SafeExamBrowser.WindowsApi.Constants;
|
|||
using SafeExamBrowser.WindowsApi.Contracts;
|
||||
using SafeExamBrowser.WindowsApi.Types;
|
||||
|
||||
namespace SafeExamBrowser.WindowsApi
|
||||
namespace SafeExamBrowser.WindowsApi.Processes
|
||||
{
|
||||
public class ProcessFactory : IProcessFactory
|
||||
{
|
|
@ -63,14 +63,15 @@
|
|||
<Compile Include="Delegates\EnumWindowsDelegate.cs" />
|
||||
<Compile Include="Delegates\EventDelegate.cs" />
|
||||
<Compile Include="Delegates\HookDelegate.cs" />
|
||||
<Compile Include="Desktop.cs" />
|
||||
<Compile Include="DesktopFactory.cs" />
|
||||
<Compile Include="DesktopMonitor.cs" />
|
||||
<Compile Include="Desktops\Desktop.cs" />
|
||||
<Compile Include="Desktops\DesktopFactory.cs" />
|
||||
<Compile Include="Desktops\DesktopMonitor.cs" />
|
||||
<Compile Include="Desktops\ObfuscatedDesktop.cs" />
|
||||
<Compile Include="ExplorerShell.cs" />
|
||||
<Compile Include="Hooks\MouseHook.cs" />
|
||||
<Compile Include="Hooks\SystemHook.cs" />
|
||||
<Compile Include="Process.cs" />
|
||||
<Compile Include="ProcessFactory.cs" />
|
||||
<Compile Include="Processes\Process.cs" />
|
||||
<Compile Include="Processes\ProcessFactory.cs" />
|
||||
<Compile Include="Constants\AccessMask.cs" />
|
||||
<Compile Include="Types\Bounds.cs" />
|
||||
<Compile Include="Types\EXECUTION_STATE.cs" />
|
||||
|
|
Loading…
Add table
Reference in a new issue