mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
use what already was working instead (#1950)
This commit is contained in:
parent
5af935bbca
commit
19464ec080
2 changed files with 17 additions and 121 deletions
|
|
@ -5,6 +5,14 @@
|
|||
#include "ntdll.h"
|
||||
#include "logging.h"
|
||||
|
||||
namespace {
|
||||
int s_dllChanged = 0;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int* GetDllChangedStorage() {
|
||||
return &s_dllChanged;
|
||||
}
|
||||
|
||||
hooks::getprocaddress_singleton_import_hook::getprocaddress_singleton_import_hook()
|
||||
: m_pfnGetProcAddress(GetProcAddress)
|
||||
, m_thunk("kernel32!GetProcAddress(Singleton Import Hook)",
|
||||
|
|
@ -71,6 +79,7 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
|
|||
m_getProcAddressHandler = set_handler(L"kernel32.dll", "GetProcAddress", m_thunk.get_thunk(), [this](void*) {});
|
||||
|
||||
LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) {
|
||||
s_dllChanged = 1;
|
||||
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) {
|
||||
const auto dllName = unicode::convert<std::string>(pData->Loaded.FullDllName->Buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,145 +1,32 @@
|
|||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Serilog;
|
||||
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Dalamud.Support;
|
||||
|
||||
/// <summary>Tracks the loaded process modules.</summary>
|
||||
[ServiceManager.EarlyLoadedService]
|
||||
internal sealed unsafe partial class CurrentProcessModules : IInternalDisposableService
|
||||
internal static unsafe partial class CurrentProcessModules
|
||||
{
|
||||
private static readonly ConcurrentQueue<string> LogQueue = new();
|
||||
private static readonly SemaphoreSlim LogSemaphore = new(0);
|
||||
|
||||
private static Process? process;
|
||||
private static nint cookie;
|
||||
|
||||
private readonly CancellationTokenSource logTaskStop = new();
|
||||
private readonly Task logTask;
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private CurrentProcessModules()
|
||||
{
|
||||
var res = LdrRegisterDllNotification(0, &DllNotificationCallback, 0, out cookie);
|
||||
if (res != STATUS.STATUS_SUCCESS)
|
||||
{
|
||||
Log.Error("{what}: LdrRegisterDllNotification failure: 0x{err}", nameof(CurrentProcessModules), res);
|
||||
cookie = 0;
|
||||
this.logTask = Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
this.logTask = Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
while (!this.logTaskStop.IsCancellationRequested)
|
||||
{
|
||||
LogSemaphore.Wait();
|
||||
while (LogQueue.TryDequeue(out var log))
|
||||
Log.Verbose(log);
|
||||
}
|
||||
},
|
||||
this.logTaskStop.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
private enum LdrDllNotificationReason : uint
|
||||
{
|
||||
Loaded = 1,
|
||||
Unloaded = 2,
|
||||
}
|
||||
|
||||
/// <summary>Gets all the loaded modules, up to date.</summary>
|
||||
public static ProcessModuleCollection ModuleCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cookie == 0)
|
||||
ref var t = ref *GetDllChangedStorage();
|
||||
if (t != 0)
|
||||
{
|
||||
// This service has not been initialized; return a fresh copy without storing it.
|
||||
return Process.GetCurrentProcess().Modules;
|
||||
}
|
||||
|
||||
if (process is null)
|
||||
t = 0;
|
||||
process = null;
|
||||
Log.Verbose("{what}: Fetchling fresh copy of current process modules.", nameof(CurrentProcessModules));
|
||||
}
|
||||
|
||||
return (process ??= Process.GetCurrentProcess()).Modules;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
if (Interlocked.Exchange(ref cookie, 0) is var copy and not 0)
|
||||
LdrUnregisterDllNotification(copy);
|
||||
if (!this.logTask.IsCompleted)
|
||||
{
|
||||
this.logTaskStop.Cancel();
|
||||
LogSemaphore.Release();
|
||||
this.logTask.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static void DllNotificationCallback(
|
||||
LdrDllNotificationReason reason,
|
||||
LdrDllNotificationData* data,
|
||||
nint context) => process = null;
|
||||
|
||||
/// <summary>
|
||||
/// Registers for notification when a DLL is first loaded.
|
||||
/// This notification occurs before dynamic linking takes place.<br /><br />
|
||||
/// <a href="https://learn.microsoft.com/en-us/windows/win32/devnotes/ldrregisterdllnotification">Docs.</a>
|
||||
/// </summary>
|
||||
/// <param name="flags">This parameter must be zero.</param>
|
||||
/// <param name="notificationFunction">A pointer to a callback function to call when the DLL is loaded.</param>
|
||||
/// <param name="context">A pointer to context data for the callback function.</param>
|
||||
/// <param name="cookie">A pointer to a variable to receive an identifier for the callback function.
|
||||
/// This identifier is used to unregister the notification callback function.</param>
|
||||
/// <returns>Returns an NTSTATUS or error code.</returns>
|
||||
[LibraryImport("ntdll.dll", SetLastError = true)]
|
||||
private static partial int LdrRegisterDllNotification(
|
||||
uint flags,
|
||||
delegate* unmanaged<LdrDllNotificationReason, LdrDllNotificationData*, nint, void>
|
||||
notificationFunction,
|
||||
nint context,
|
||||
out nint cookie);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels DLL load notification previously registered by calling the LdrRegisterDllNotification function.<br />
|
||||
/// <br />
|
||||
/// <a href="https://learn.microsoft.com/en-us/windows/win32/devnotes/ldrunregisterdllnotification">Docs.</a>
|
||||
/// </summary>
|
||||
/// <param name="cookie">A pointer to the callback identifier received from the LdrRegisterDllNotification call
|
||||
/// that registered for notification.
|
||||
/// </param>
|
||||
/// <returns>Returns an NTSTATUS or error code.</returns>
|
||||
[LibraryImport("ntdll.dll", SetLastError = true)]
|
||||
private static partial int LdrUnregisterDllNotification(nint cookie);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct LdrDllNotificationData
|
||||
{
|
||||
/// <summary>Reserved.</summary>
|
||||
public uint Flags;
|
||||
|
||||
/// <summary>The full path name of the DLL module.</summary>
|
||||
public UNICODE_STRING* FullDllName;
|
||||
|
||||
/// <summary>The base file name of the DLL module.</summary>
|
||||
public UNICODE_STRING* BaseDllName;
|
||||
|
||||
/// <summary>A pointer to the base address for the DLL in memory.</summary>
|
||||
public nint DllBase;
|
||||
|
||||
/// <summary>The size of the DLL image, in bytes.</summary>
|
||||
public uint SizeOfImage;
|
||||
}
|
||||
[LibraryImport("Dalamud.Boot.dll")]
|
||||
private static partial int* GetDllChangedStorage();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue