mirror of https://github.com/dahall/Vanara.git
Added in PR #386 to branch
parent
b2a78e184b
commit
c5605d51b8
|
@ -210,6 +210,12 @@ public static partial class NtDll
|
|||
/// <summary>Reserved.</summary>
|
||||
MaxSubsystemInformationType,
|
||||
}
|
||||
|
||||
/// <summary>Set the debug object handle in the TEB. This function is UNDOCUMENTED.</summary>
|
||||
/// <param name="DebugObjectHandle">Debug object handle. Retrieve from NtQueryInformationProcess</param>
|
||||
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
|
||||
public static extern void DbgUiSetThreadDebugObject(IntPtr DebugObjectHandle);
|
||||
|
||||
/// <summary>Creates a process. This function is UNDOCUMENTED.</summary>
|
||||
/// <param name="ProcessHandle">The process handle.</param>
|
||||
/// <param name="DesiredAccess">The desired access.</param>
|
||||
|
@ -524,7 +530,7 @@ public static partial class NtDll
|
|||
if (ret.Succeeded)
|
||||
return res;
|
||||
if (ret != NTStatus.STATUS_INFO_LENGTH_MISMATCH || qsz == 0)
|
||||
throw ret.GetException();
|
||||
throw ret.GetException()!;
|
||||
res.Size = qsz;
|
||||
NtWow64QueryInformationProcess64(ProcessHandle, ProcessInformationClass, ((IntPtr)res).ToInt32(), res.Size, out _).ThrowIfFailed();
|
||||
return res;
|
||||
|
@ -538,7 +544,7 @@ public static partial class NtDll
|
|||
if (status.Succeeded)
|
||||
return mem;
|
||||
if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0)
|
||||
throw status.GetException();
|
||||
throw status.GetException()!;
|
||||
mem.Size = sz;
|
||||
NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out _).ThrowIfFailed();
|
||||
return mem;
|
||||
|
@ -551,6 +557,20 @@ public static partial class NtDll
|
|||
/// <returns><see langword="true"/> if structures returned from <c>NtQueryInformationProcess</c> must be configured exclusively for 64-bit use.</returns>
|
||||
public static bool NtQueryInformationProcessRequiresWow64Structs(HPROCESS ProcessHandle) => IsWow64(Kernel32.GetCurrentProcess()) && !IsWow64(ProcessHandle);
|
||||
|
||||
/// <summary>Call the kernel to remove the debug object. This function is UNDOCUMENTED.</summary>
|
||||
/// <param name="ProcessHandle">The process handle.</param>
|
||||
/// <param name="DebugObjectHandle">Debug object handle. Retrieve from NtQueryInformationProcess</param>
|
||||
/// <returns>
|
||||
/// <para>The function returns an NTSTATUS success or error code.</para>
|
||||
/// <para>
|
||||
/// The forms and significance of NTSTATUS error codes are listed in the Ntstatus.h header file available in the DDK, and are
|
||||
/// described in the DDK documentation under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques /
|
||||
/// Logging Errors.
|
||||
/// </para>
|
||||
/// </returns>
|
||||
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
|
||||
public static extern NTStatus NtRemoveProcessDebug(HPROCESS ProcessHandle, IntPtr DebugObjectHandle);
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// [ <c>NtQueryInformationProcess</c> may be altered or unavailable in future versions of Windows. Applications should use the
|
||||
|
|
|
@ -68,4 +68,58 @@ public partial class WinternlTests
|
|||
Assert.That(() => ppb = NtQueryInformationProcess<uint>(hProc, PROCESSINFOCLASS.ProcessPriorityBoost), Throws.Nothing);
|
||||
TestContext.WriteLine($"Priority boost: {ppb.Value}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DbgUiSetThreadDebugObjectAndNtRemoveProcessDebugTest()
|
||||
{
|
||||
Kernel32.STARTUPINFO StartInfo = new()
|
||||
{
|
||||
dwFlags = Kernel32.STARTF.STARTF_USESHOWWINDOW,
|
||||
wShowWindow = (ushort)ShowWindowCommand.SW_HIDE
|
||||
};
|
||||
Assert.That(Kernel32.CreateProcess(@"C:\Program Files\Notepad++\notepad++.exe", dwCreationFlags: Kernel32.CREATE_PROCESS.DEBUG_PROCESS | Kernel32.CREATE_PROCESS.CREATE_UNICODE_ENVIRONMENT, lpStartupInfo: StartInfo, lpProcessInformation: out Kernel32.SafePROCESS_INFORMATION Information), ResultIs.Successful);
|
||||
using (Information)
|
||||
using (NtQueryResult<IntPtr> DebugObjectHandleQueryResult = NtQueryInformationProcess<IntPtr>(Information.hProcess, PROCESSINFOCLASS.ProcessDebugObjectHandle))
|
||||
{
|
||||
Assert.That(DebugObjectHandleQueryResult, ResultIs.ValidHandle);
|
||||
Assert.That(DebugObjectHandleQueryResult.Value, ResultIs.ValidHandle);
|
||||
|
||||
try
|
||||
{
|
||||
DbgUiSetThreadDebugObject(DebugObjectHandleQueryResult.Value);
|
||||
|
||||
try
|
||||
{
|
||||
Kernel32.SafeHPROCESS DebugProcessHandle = Kernel32.SafeHPROCESS.Null;
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Assert.That(Kernel32.WaitForDebugEvent(out Kernel32.DEBUG_EVENT Event, Kernel32.INFINITE), ResultIs.Successful);
|
||||
if (Event.dwDebugEventCode == Kernel32.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT)
|
||||
{
|
||||
DebugProcessHandle = new Kernel32.SafeHPROCESS(Event.u.CreateProcessInfo.hProcess);
|
||||
break;
|
||||
}
|
||||
Assert.That(Kernel32.ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, Kernel32.DEBUG_CONTINUE.DBG_CONTINUE), ResultIs.Successful);
|
||||
}
|
||||
Assert.False(DebugProcessHandle.IsNull);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DebugProcessHandle.Dispose();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
DbgUiSetThreadDebugObject(IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Assert.That(Kernel32.TerminateProcess(Information.hProcess, 0), ResultIs.Successful);
|
||||
Assert.That(NtRemoveProcessDebug(Information.hProcess, DebugObjectHandleQueryResult.Value), ResultIs.Successful);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue