Skip to content

Commit 31a152b

Browse files
committed
WIP
1 parent 3a7d37d commit 31a152b

File tree

2 files changed

+75
-40
lines changed

2 files changed

+75
-40
lines changed

Source/ManagedTest/ManagedTest.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@
9090
<ItemGroup>
9191
<None Include="App.config" />
9292
</ItemGroup>
93+
<ItemGroup>
94+
<ProjectReference Include="..\Sysinternals.Debug\Sysinternals.Debug.csproj">
95+
<Project>{fb1d522e-1acb-49dd-93d4-123e6ea13aed}</Project>
96+
<Name>Sysinternals.Debug</Name>
97+
</ProjectReference>
98+
</ItemGroup>
9399
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
94100
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
95101
Other similar extension points exist, see Microsoft.Common.targets.

Source/Sysinternals.Debug/NativeMethods.cs

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,107 @@
88
// - Moved to VS 2013 and .NET 4.5.1
99
//////////////////////////////////////////////////////////////////////////////*/
1010

11+
using System.Text;
12+
using Microsoft.Win32.SafeHandles;
13+
1114
namespace Sysinternals.Debug
1215
{
1316
using System;
1417
using System.Diagnostics;
15-
using System.Reflection;
1618
using System.Runtime.InteropServices;
1719

1820
/// <summary>
1921
/// A class to wrap all the native code needed by this assembly.
2022
/// </summary>
2123
internal static class NativeMethods
2224
{
25+
// Constants to represent C preprocessor macros for PInvokes
26+
const uint GENERIC_WRITE = 0x40000000;
27+
const uint OPEN_EXISTING = 3;
28+
const uint FILE_WRITE_ACCESS = 0x0002;
29+
const uint FILE_SHARE_WRITE = 0x00000002;
30+
const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
31+
const uint METHOD_BUFFERED = 0;
32+
33+
// Procmon Constants
34+
const uint FILE_DEVICE_PROCMON_LOG = 0x00009535;
35+
const string PROCMON_DEBUGGER_HANDLER = "\\\\.\\Global\\ProcmonDebugLogger";
36+
2337
/// <summary>
24-
/// Flag to check if we've already done the process lookup.
38+
/// The handle to the procmon log device.
2539
/// </summary>
26-
private static bool lookedUpProcessType;
40+
private static SafeFileHandle hProcMon;
2741

2842
/// <summary>
29-
/// True if the process is 64-bit.
43+
/// Get the IO Control code for the ProcMon log.
3044
/// </summary>
31-
private static bool is64BitProcess;
45+
private static uint IOCTL_EXTERNAL_LOG_DEBUGOUT { get { return CTL_CODE(); } }
46+
47+
/// <seealso href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff543023(v=vs.85).aspx"/>
48+
private static uint CTL_CODE(
49+
uint DeviceType = FILE_DEVICE_PROCMON_LOG,
50+
uint Function = 0x81,
51+
uint Method = METHOD_BUFFERED,
52+
uint Access = FILE_WRITE_ACCESS)
53+
{
54+
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
55+
}
56+
57+
/// <remarks>This is only used for opening the procmon log handle, hence the default parameters.</remarks>
58+
/// <seealso href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx"/>
59+
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
60+
private static extern SafeFileHandle CreateFile(
61+
string lpFileName = PROCMON_DEBUGGER_HANDLER,
62+
uint dwDesiredAccess = GENERIC_WRITE,
63+
uint dwShareMode = FILE_SHARE_WRITE,
64+
IntPtr lpSecurityAttributes = default(IntPtr),
65+
uint dwCreationDisposition = OPEN_EXISTING,
66+
uint dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
67+
IntPtr hTemplateFile = default(IntPtr));
68+
69+
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
70+
private static extern bool DeviceIoControl(
71+
SafeFileHandle hDevice, uint dwIoControlCode,
72+
StringBuilder lpInBuffer, uint nInBufferSize,
73+
IntPtr lpOutBuffer, uint nOutBufferSize,
74+
out uint lpBytesReturned, IntPtr lpOverlapped);
75+
76+
static NativeMethods()
77+
{
78+
AppDomain.CurrentDomain.ProcessExit += (sender, args) =>
79+
{
80+
if (!hProcMon.IsInvalid) hProcMon.Close();
81+
};
82+
}
3283

3384
/// <summary>
3485
/// Does the actual tracing to Process Monitor.
3586
/// </summary>
3687
/// <param name="message">
3788
/// The message to display.
3889
/// </param>
90+
/// <param name="args">
91+
/// The formatting arguments for the message
92+
/// </param>
3993
/// <returns>
4094
/// True if the trace succeeded, false otherwise.
4195
/// </returns>
42-
public static bool ProcMonDebugOutput(string message)
96+
public static bool ProcMonDebugOutput(string message, params object[] args)
4397
{
44-
if (false == lookedUpProcessType)
45-
{
46-
lookedUpProcessType = true;
47-
48-
Assembly mscorlibAssem = Assembly.GetAssembly(typeof(object));
49-
Module[] mods = mscorlibAssem.GetModules();
50-
PortableExecutableKinds peK;
51-
ImageFileMachine ifn;
52-
mods[0].GetPEKind(out peK, out ifn);
53-
is64BitProcess = ImageFileMachine.I386 != ifn;
54-
}
55-
5698
bool returnValue = false;
5799
try
58100
{
59-
if (true == is64BitProcess)
60-
{
61-
returnValue = ProcMonDebugOutputx64(message);
62-
}
63-
else
101+
StringBuilder renderedMessage = new StringBuilder();
102+
renderedMessage.AppendFormat(message, args);
103+
uint outLen;
104+
if (hProcMon == null || hProcMon.IsInvalid)
64105
{
65-
returnValue = ProcMonDebugOutputWin32(message);
106+
hProcMon = CreateFile();
66107
}
108+
DeviceIoControl(
109+
hProcMon, IOCTL_EXTERNAL_LOG_DEBUGOUT,
110+
renderedMessage, (uint)(message.Length * Marshal.SizeOf(typeof(char))),
111+
IntPtr.Zero, 0, out outLen, IntPtr.Zero);
67112
}
68113
catch (EntryPointNotFoundException notFoundException)
69114
{
@@ -75,21 +120,5 @@ public static bool ProcMonDebugOutput(string message)
75120

76121
return returnValue;
77122
}
78-
79-
[DllImport("ProcMonDebugOutputx64.dll",
80-
CharSet = CharSet.Unicode,
81-
EntryPoint = "ProcMonDebugOutput",
82-
SetLastError = true,
83-
CallingConvention = CallingConvention.StdCall)]
84-
[return: MarshalAs(UnmanagedType.Bool)]
85-
private static extern bool ProcMonDebugOutputx64(string lpOutput);
86-
87-
[DllImport("ProcMonDebugOutputWin32.dll",
88-
CharSet = CharSet.Unicode,
89-
EntryPoint = "ProcMonDebugOutput",
90-
SetLastError = true,
91-
CallingConvention = CallingConvention.StdCall)]
92-
[return: MarshalAs(UnmanagedType.Bool)]
93-
private static extern bool ProcMonDebugOutputWin32(string lpOutput);
94123
}
95124
}

0 commit comments

Comments
 (0)