66 lines
1.9 KiB
C#
66 lines
1.9 KiB
C#
/*
|
|
* Copyright (c) 2024 ETH Zürich, IT Services
|
|
*
|
|
* 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.Threading;
|
|
using SafeExamBrowser.WindowsApi.Constants;
|
|
using SafeExamBrowser.WindowsApi.Contracts.Events;
|
|
using SafeExamBrowser.WindowsApi.Delegates;
|
|
|
|
namespace SafeExamBrowser.WindowsApi.Hooks
|
|
{
|
|
internal class SystemHook
|
|
{
|
|
private SystemEventCallback callback;
|
|
private AutoResetEvent detachEvent, detachResultAvailableEvent;
|
|
private bool detachSuccess;
|
|
private EventDelegate eventDelegate;
|
|
private uint eventId;
|
|
private IntPtr handle;
|
|
|
|
internal Guid Id { get; private set; }
|
|
|
|
public SystemHook(SystemEventCallback callback, uint eventId)
|
|
{
|
|
this.callback = callback;
|
|
this.detachEvent = new AutoResetEvent(false);
|
|
this.detachResultAvailableEvent = new AutoResetEvent(false);
|
|
this.eventId = eventId;
|
|
this.Id = Guid.NewGuid();
|
|
}
|
|
|
|
internal void Attach()
|
|
{
|
|
// IMPORTANT:
|
|
// 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!
|
|
eventDelegate = new EventDelegate(LowLevelSystemProc);
|
|
handle = User32.SetWinEventHook(eventId, eventId, IntPtr.Zero, eventDelegate, 0, 0, Constant.WINEVENT_OUTOFCONTEXT);
|
|
}
|
|
|
|
internal void AwaitDetach()
|
|
{
|
|
detachEvent.WaitOne();
|
|
detachSuccess = User32.UnhookWinEvent(handle);
|
|
detachResultAvailableEvent.Set();
|
|
}
|
|
|
|
internal bool Detach()
|
|
{
|
|
detachEvent.Set();
|
|
detachResultAvailableEvent.WaitOne();
|
|
|
|
return detachSuccess;
|
|
}
|
|
|
|
private void LowLevelSystemProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
|
|
{
|
|
callback(hwnd);
|
|
}
|
|
}
|
|
}
|