88// - Moved to VS 2013 and .NET 4.5.1
99//////////////////////////////////////////////////////////////////////////////*/
1010
11- using System . Text ;
12- using Microsoft . Win32 . SafeHandles ;
13-
1411namespace Sysinternals . Debug
1512{
13+ using Microsoft . Win32 . SafeHandles ;
1614 using System ;
1715 using System . Diagnostics ;
16+ using System . Diagnostics . CodeAnalysis ;
17+ using System . Globalization ;
1818 using System . Runtime . InteropServices ;
19+ using System . Security ;
20+ using System . Text ;
1921
2022 /// <summary>
2123 /// A class to wrap all the native code needed by this assembly.
2224 /// </summary>
25+ [ SuppressMessage ( "Microsoft.Portability" ,
26+ "CA1903:UseOnlyApiFromTargetedFramework" ,
27+ MessageId = "System.Security.SecuritySafeCriticalAttribute" ,
28+ Justification = "Everyone is running .NET 2.0 SP2 so they have SecuritySafeCritical" ) ]
29+ [ SecuritySafeCritical ]
2330 internal static class NativeMethods
2431 {
2532 // 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 ;
33+ private const uint GENERIC_WRITE = 0x40000000 ;
34+ private const uint OPEN_EXISTING = 3 ;
35+ private const uint FILE_WRITE_ACCESS = 0x0002 ;
36+ private const uint FILE_SHARE_WRITE = 0x00000002 ;
37+ private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080 ;
38+ private const uint METHOD_BUFFERED = 0 ;
3239
33- // Procmon Constants
34- const uint FILE_DEVICE_PROCMON_LOG = 0x00009535 ;
35- const string PROCMON_DEBUGGER_HANDLER = "\\ \\ .\\ Global\\ ProcmonDebugLogger" ;
40+ // Process Monitor Constants
41+ private const uint FILE_DEVICE_PROCMON_LOG = 0x00009535 ;
42+ private const string PROCMON_DEBUGGER_HANDLER = "\\ \\ .\\ Global\\ ProcmonDebugLogger" ;
3643
3744 /// <summary>
38- /// The handle to the procmon log device.
45+ /// The handle to the Process Monitor log device.
3946 /// </summary>
4047 private static SafeFileHandle hProcMon ;
4148
4249 /// <summary>
43- /// Get the IO Control code for the ProcMon log.
50+ /// Gets the IO Control code for the ProcMon log.
4451 /// </summary>
4552 private static uint IOCTL_EXTERNAL_LOG_DEBUGOUT { get { return CTL_CODE ( ) ; } }
4653
54+ /// <summary>
55+ /// Builds the control code for the Process Monitor driver access.
56+ /// </summary>
4757 /// <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 )
58+ private static uint CTL_CODE ( uint DeviceType = FILE_DEVICE_PROCMON_LOG ,
59+ uint Function = 0x81 ,
60+ uint Method = METHOD_BUFFERED ,
61+ uint Access = FILE_WRITE_ACCESS )
5362 {
5463 return ( ( DeviceType << 16 ) | ( Access << 14 ) | ( Function << 2 ) | Method ) ;
5564 }
5665
57- /// <remarks>This is only used for opening the procmon log handle, hence the default parameters.</remarks>
66+ /// <summary>
67+ /// Handles calling CreateFile.
68+ /// </summary>
69+ /// <remarks>
70+ /// This is only used for opening the Process Monitor log handle, hence the default parameters.
71+ /// </remarks>
5872 /// <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 ) ) ;
73+ [ SuppressMessage ( "Microsoft.Security" ,
74+ "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule" ,
75+ Justification = "This is a bug in Code Analysis on pre-4.0 assemblies: http://connect.microsoft.com/VisualStudio/feedback/details/729254/bogus-ca5122-warning-about-p-invoke-declarations-should-not-be-safe-critical" ) ]
76+ [ DllImport ( "kernel32.dll" ,
77+ SetLastError = true ,
78+ CharSet = CharSet . Unicode ) ]
79+ private static extern SafeFileHandle CreateFile ( string lpFileName = PROCMON_DEBUGGER_HANDLER ,
80+ uint dwDesiredAccess = GENERIC_WRITE ,
81+ uint dwShareMode = FILE_SHARE_WRITE ,
82+ IntPtr lpSecurityAttributes = default ( IntPtr ) ,
83+ uint dwCreationDisposition = OPEN_EXISTING ,
84+ uint dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL ,
85+ IntPtr hTemplateFile = default ( IntPtr ) ) ;
6886
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 ) ;
87+ [ SuppressMessage ( "Microsoft.Security" ,
88+ "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule" ,
89+ Justification = "This is a bug in Code Analysis on pre-4.0 assemblies: http://connect.microsoft.com/VisualStudio/feedback/details/729254/bogus-ca5122-warning-about-p-invoke-declarations-should-not-be-safe-critical" ) ]
90+ [ DllImport ( "kernel32.dll" ,
91+ ExactSpelling = true ,
92+ SetLastError = true ,
93+ CharSet = CharSet . Unicode ) ]
94+ [ return : MarshalAs ( UnmanagedType . Bool ) ]
95+ private static extern bool DeviceIoControl ( SafeFileHandle hDevice ,
96+ uint dwIoControlCode ,
97+ StringBuilder lpInBuffer ,
98+ uint nInBufferSize ,
99+ IntPtr lpOutBuffer ,
100+ uint nOutBufferSize ,
101+ out uint lpBytesReturned ,
102+ IntPtr lpOverlapped ) ;
75103
104+ [ SuppressMessage ( "Microsoft.Performance" ,
105+ "CA1810:InitializeReferenceTypeStaticFieldsInline" ,
106+ Justification = "How else are you going to set up a static event? (http://social.msdn.microsoft.com/Forums/en-US/d11fe313-278c-4cae-bfcc-b119204866c7/ca1810-incorrect?forum=vstscode)" ) ]
76107 static NativeMethods ( )
77108 {
78109 AppDomain . CurrentDomain . ProcessExit += ( sender , args ) =>
79110 {
80- if ( ! hProcMon . IsInvalid ) hProcMon . Close ( ) ;
111+ if ( ! hProcMon . IsInvalid )
112+ {
113+ hProcMon . Close ( ) ;
114+ }
81115 } ;
82116 }
83117
@@ -96,28 +130,23 @@ static NativeMethods()
96130 public static bool ProcMonDebugOutput ( string message , params object [ ] args )
97131 {
98132 bool returnValue = false ;
99- try
100- {
101- StringBuilder renderedMessage = new StringBuilder ( ) ;
102- renderedMessage . AppendFormat ( message , args ) ;
103- uint outLen ;
104- if ( hProcMon == null || hProcMon . IsInvalid )
105- {
106- hProcMon = CreateFile ( ) ;
107- }
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 ) ;
112- }
113- catch ( EntryPointNotFoundException notFoundException )
133+ StringBuilder renderedMessage = new StringBuilder ( ) ;
134+ renderedMessage . AppendFormat ( CultureInfo . CurrentCulture , message , args ) ;
135+ uint outLen ;
136+
137+ if ( hProcMon == null || hProcMon . IsInvalid )
114138 {
115- // This means the appropriate ProcMonDebugOutput[Win32|x64].DLL
116- // file could not be found. I'll eat this exception so it does
117- // not take down the application.
118- Debug . WriteLine ( notFoundException . Message ) ;
139+ hProcMon = CreateFile ( ) ;
119140 }
120141
142+ returnValue = DeviceIoControl ( hProcMon ,
143+ IOCTL_EXTERNAL_LOG_DEBUGOUT ,
144+ renderedMessage ,
145+ ( uint ) ( message . Length * sizeof ( System . Char ) ) ,
146+ IntPtr . Zero ,
147+ 0 ,
148+ out outLen ,
149+ IntPtr . Zero ) ;
121150 return returnValue ;
122151 }
123152 }
0 commit comments